KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > services > controller > SimpleLoginController


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64
65 package com.jcorporate.expresso.services.controller;
66
67 import com.jcorporate.expresso.core.ExpressoConstants;
68 import com.jcorporate.expresso.core.controller.Controller;
69 import com.jcorporate.expresso.core.controller.ControllerException;
70 import com.jcorporate.expresso.core.controller.ControllerRequest;
71 import com.jcorporate.expresso.core.controller.ControllerResponse;
72 import com.jcorporate.expresso.core.controller.ErrorCollection;
73 import com.jcorporate.expresso.core.controller.Input;
74 import com.jcorporate.expresso.core.controller.NonHandleableException;
75 import com.jcorporate.expresso.core.controller.Output;
76 import com.jcorporate.expresso.core.controller.ServletControllerRequest;
77 import com.jcorporate.expresso.core.controller.State;
78 import com.jcorporate.expresso.core.controller.Transition;
79 import com.jcorporate.expresso.core.controller.session.PersistentSession;
80 import com.jcorporate.expresso.core.dataobjects.Securable;
81 import com.jcorporate.expresso.core.db.DBException;
82 import com.jcorporate.expresso.core.dbobj.DBObject;
83 import com.jcorporate.expresso.core.dbobj.ValidValue;
84 import com.jcorporate.expresso.core.i18n.Messages;
85 import com.jcorporate.expresso.core.misc.ConfigManager;
86 import com.jcorporate.expresso.core.misc.ConfigurationException;
87 import com.jcorporate.expresso.core.misc.SerializableString;
88 import com.jcorporate.expresso.core.misc.StringUtil;
89 import com.jcorporate.expresso.core.security.User;
90 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
91 import com.jcorporate.expresso.services.dbobj.RegistrationDomain;
92 import com.jcorporate.expresso.services.dbobj.Setup;
93 import com.jcorporate.expresso.services.validation.AuthValidationException;
94 import com.jcorporate.expresso.services.validation.ValidationEntry;
95 import org.apache.log4j.Logger;
96 import org.apache.struts.Globals;
97 import org.apache.struts.action.ActionForward;
98 import org.apache.struts.config.ForwardConfig;
99
100 import javax.servlet.ServletException JavaDoc;
101 import javax.servlet.http.HttpServletRequest JavaDoc;
102 import javax.servlet.http.HttpServletResponse JavaDoc;
103 import java.util.Enumeration JavaDoc;
104 import java.util.Vector JavaDoc;
105
106 /**
107  * Main Login Controller - used for login/logout and basic interaction with
108  * the registration system. This class recognizes the 'registration' classHandler
109  * name in the expresso-config.xml It uses the classname in that field to
110  * construct and forward to the appropriate registration class.
111  */

112 public class SimpleLoginController
113         extends LoginController {
114
115     private static Logger log = Logger.getLogger(SimpleLoginController.class);
116
117     /**
118      * LoginController constructor. Sets all the states and parameters
119      * for the system.
120      */

121     public SimpleLoginController() {
122         super();
123         State promptLogin = new State("promptLogin", "Prompt Login");
124         promptLogin.addOptionalParameter("next"); //Where do we link after login?
125
promptLogin.addOptionalParameter("immediate"); //Do we even display the
126
//confirmation page or do we
127
//just jump straight to the
128
//page on success? Y or N
129
promptLogin.setSecure(true);
130         promptLogin.addOptionalParameter("next"); //Where do we link after login?
131
promptLogin.addOptionalParameter("immediate"); //Do we even display the
132
//confirmation page or do we
133
//just jump straight to the
134
//page on success?
135
promptLogin.addOptionalParameter("LoginName");
136         addState(promptLogin);
137
138         State processLogin = new State("processLogin", "Login");
139         processLogin.setSecure(true);
140         addState(processLogin);
141
142         State processLogout = new State("processLogout", "Logout");
143         addState(processLogout);
144
145         State promptChangePassword = new State("promptChangePassword",
146                 "Prompt Change Password");
147         promptChangePassword.setSecure(true);
148         addState(promptChangePassword);
149
150
151         State processChangePassword = new State("processChangePassword",
152                 "Change Password");
153         processChangePassword.setSecure(true);
154         addState(processChangePassword);
155
156         State emailValidate = new State("emailValidate", "Validate User's Email Address");
157         emailValidate.addRequiredParameter("db");
158         emailValidate.addRequiredParameter("UserName");
159         emailValidate.addOptionalParameter("loginController");
160         addState(emailValidate);
161
162         State promptSendPassword = new State("promptSendPassword",
163                 "Prompt Send Password");
164         addState(promptSendPassword);
165
166         State processSendPassword = new State("processSendPassword",
167                 "Reset & Send Password");
168         processSendPassword.addParameter("Email",
169                 false,
170                 DBObject.EMAIL_MASK,
171                 "You must enter a valid email address");
172         addState(processSendPassword);
173
174         State s = new State("promptRevalidate", "Prompt Revalidate");
175         this.addState(s);
176
177         s = new State("processRevalidate", "Process Revalidate");
178         s.addParameter("Email", false,
179                 DBObject.EMAIL_MASK, "You must enter a valid email address");
180         this.addState(s);
181
182         setInitialState("promptLogin");
183         this.setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
184     }
185
186
187     /**
188      * If the user has validated the email sent to validate change password request,
189      * then this method actually resets thepassword and sends notification.
190      *
191      * @param request The framework controller request
192      * @param response The framework ControllerResponse object
193      * @throws ControllerException upon logic error
194      * @throws NonHandleableException upon fatal error
195      */

196     protected void runEmailValidateState(ControllerRequest request,
197                                          ControllerResponse response)
198             throws ControllerException,
199             NonHandleableException {
200 // The db context for the user (Note: this is different from the Validation entry context, which
201
// could very well be in a different DB context)
202
String JavaDoc dbname = StringUtil.notNull(request.getParameter("db"));
203
204 // The login name of the user
205
String JavaDoc loginName = StringUtil.notNull(request.getParameter("UserName"));
206         String JavaDoc registrationController = StringUtil.notNull(request.getParameter("RegistrationController"));
207         if (registrationController.length() == 0) {
208             registrationController = this.getDefaultRegistrationController().getClass().getName();
209         }
210
211         String JavaDoc loginController = StringUtil.notNull(request.getParameter("LoginController"));
212         try {
213             ErrorCollection errors = new ErrorCollection();
214
215 // Make sure that the user with this loginName actually exists
216
User user = new User();
217             user.setDataContext(dbname);
218             user.setLoginName(loginName);
219
220             if (!user.find()) {
221 //errors.addError("Account \"" + loginName + "\" not found");
222
errors.addError("login.accountnotfound", (Object JavaDoc) loginName);
223             }
224 // Make sure the User record has not been disabled for some reason
225
if (errors.isEmpty()) {
226                 if (user.getAccountStatus().equals("D")) {
227                     errors.addError("error.login.accountdisabled", (Object JavaDoc) loginName);
228                 }
229             }
230
231             if (!errors.isEmpty()) {
232                 response.saveErrors(errors);
233                 return;
234             }
235
236 // Reset the user's password and send email
237
String JavaDoc password = null;
238             if (errors.isEmpty()) {
239                 password = user.randomPassword();
240                 user.setPassword(password);
241                 user.setAccountStatus("A");
242                 user.update();
243
244                 FastStringBuffer msg = FastStringBuffer.getInstance();
245                 msg.append(response.getString("passwdReset", loginName,
246                         password,
247                         Setup.getValue(request.getDataContext(),
248                                 "CompanyName"),
249                         Setup.getValue(request.getDataContext(),
250                                 "HomePageURL")));
251                 user.notify(response.getString("passwdResetSubject"),
252                         msg.toString());
253                 msg.release();
254             }
255 // If no errors happened so far, just create an Output to state
256
// the success and what happened
257
if (errors.isEmpty()) {
258                 Output o = new Output("successMessage",
259                         "Password succesfully reset and email sent to user \"" +
260                         loginName + "\" ");
261                 response.add(o);
262                 FastStringBuffer msg = FastStringBuffer.getInstance();
263                 try {
264                     msg.append("You may log into the system using the password: \n");
265                     msg.append(password);
266                     msg.append("\n This password has been emailed to you ");
267                     msg.append("and should be kept in a safe place");
268
269                     response.add(new Output("passwordMessage", msg.toString()));
270                 } finally {
271                     msg.release();
272                 }
273
274                 Transition login = new Transition();
275                 login.setLabel("Log In");
276                 login.setName("promptLogin");
277                 login.addParam(Controller.CONTROLLER_PARAM_KEY,
278                         loginController);
279                 login.addParam("dbContext", dbname);
280                 response.add(login);
281
282                 Transition register = new Transition();
283                 register.setLabel("Register");
284                 register.setName("promptSelfRegister");
285                 register.addParam(Controller.CONTROLLER_PARAM_KEY,
286                         registrationController);
287                 register.addParam("dbContext", dbname);
288                 response.add(register);
289             } else {
290
291 // Errors happened, add the error collection to the response
292
response.saveErrors(errors);
293             }
294         } catch (DBException dbe) {
295             throw new ControllerException("DB error", dbe);
296         }
297
298     }
299
300
301     /**
302      * @return the title of this controller
303      */

304     public String JavaDoc getTitle() {
305         return ("Expresso Login");
306     }
307
308
309     /**
310      * Processes the "change my password" request.
311      *
312      * @param request The framework controller request
313      * @param response The framework ControllerResponse object
314      * @throws ControllerException upon logic error
315      * @throws NonHandleableException upon fatal error
316      */

317     protected void runProcessChangePasswordState(ControllerRequest request,
318                                                  ControllerResponse response)
319             throws ControllerException,
320             NonHandleableException {
321         ErrorCollection errors = new ErrorCollection();
322         String JavaDoc loginName = request.getUser();
323
324         try {
325             User myUser = new User();
326             myUser.setDataContext(request.getDataContext());
327             myUser.setLoginName(loginName);
328
329             if (loginName.equals("") || loginName.equals(User.UNKNOWN_USER) ||
330                     !myUser.find()) {
331                 delayLogin(); //Slow 'em down
332
errors.addError(response.getString("error.login.mustloginchngpaswd"));
333             } else if (!myUser.passwordEquals(StringUtil.notNull(request.getParameter("oldPassword")))) {
334                 errors.addError(response.getString("error.login.passwordinvalid", loginName));
335             }
336             if (errors.getErrorCount() < 1) {
337                 if (!myUser.getAccountStatus().equals("A")) {
338                     log.warn("User \"" + loginName +
339                             "\" attempted changin password, denied because account status is \"" +
340                             myUser.getAccountStatus() + "\"");
341                     delayLogin(); //Slow 'em down
342
errors.addError(response.getString("error.login.disablednochngpaswd", loginName));
343                 }
344             }
345             if (errors.getErrorCount() < 1) {
346                 if (!request.getParameter("Password").equals(request.getParameter("password_verify"))) {
347
348                     //password and verify do not match. Add an error.
349
errors.addError("error.login.passwdnomatch");
350                 }
351             }
352             if (errors.getErrorCount() < 1) {
353                 User user = new User();
354                 user.setDataContext(request.getDataContext());
355                 user.setUid(request.getUid());
356                 user.retrieve();
357                 user.setPassword(request.getParameter("Password"));
358                 user.update();
359             }
360         } catch (DBException dbe) {
361             throw new ControllerException(dbe);
362         } finally {
363             if (errors.getErrorCount() < 1) {
364                 response.clearFormCache();
365
366                 Output successMessage = new Output("successMessage",
367                         response.getString("PasswordChangeSuccess", loginName));
368                 response.addOutput(successMessage);
369                 response.addTransition(new Transition("promptChangePassword",
370                         this));
371                 response.addTransition(new Transition("promptLogin", this));
372                 response.addTransition(new Transition("processLogout", this));
373
374                 Transition editPref = new Transition();
375                 editPref.setName("editPreferences");
376                 editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
377                         "com.jcorporate.expresso.services.controller.EditUserPreference");
378                 editPref.addParam(STATE_PARAM_KEY, "edit");
379                 response.add(editPref);
380
381                 Transition showDBMenu = new Transition();
382                 showDBMenu.setName("showDBMenu");
383                 showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
384                         this.getDefaultRegistrationController().getClass().getName());
385                 showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
386                 response.add(showDBMenu);
387             } else {
388                 response.saveErrors(errors);
389                 response.setFormCache();
390                 transition("promptChangePassword", request, response);
391             }
392         }
393     }
394
395     /**
396      * Processes the login request.... loops back to the promptLoginState
397      * if there's an error processing this system.
398      *
399      * @param request The framework controller request
400      * @param response The framework ControllerResponse object
401      * @throws ControllerException upon logic error
402      * @throws NonHandleableException upon fatal error
403      */

404     protected void runProcessLoginState(ControllerRequest request,
405                                         ControllerResponse response)
406             throws ControllerException,
407             NonHandleableException {
408         ErrorCollection errors = new ErrorCollection();
409         PersistentSession session = request.getSession();
410         String JavaDoc destination = null;
411
412         /* Normally, accessing the HttpServletRequest/Response objects is a very bad
413         * idea. The fact that this controller does it means that it is non-portable
414         * outside the servlet environment
415         */

416         ServletControllerRequest sr = (ServletControllerRequest) request;
417         HttpServletResponse JavaDoc hres = (HttpServletResponse JavaDoc) sr.getServletResponse();
418         HttpServletRequest JavaDoc hreq = (HttpServletRequest JavaDoc) sr.getServletRequest();
419         String JavaDoc dbContext = StringUtil.notNull(request.getParameter("dbContext"));
420         request.setDataContext(dbContext);
421
422         //
423
//Remove wildcards so that it isn't used in finding users.
424
//
425
String JavaDoc loginName = StringUtil.replaceAll(StringUtil.notNull(request.getParameter("LoginName"))
426                 , "%", "");
427         int uid = 0;
428
429         try {
430             uid = attemptLogin(request, response, errors, hreq,
431                     hres, session);
432         } catch (DBException dbe) {
433             throw new ControllerException(dbe);
434         } finally {
435             if (errors.getErrorCount() > 0) {
436                 log.debug("Transitioning back to login state...");
437                 response.saveErrors(errors);
438                 response.setFormCache();
439                 transition("promptLogin", request, response);
440
441                 return;
442             }
443
444             ///////////////////////////////////////
445
// good login
446
///////////////////////////////////////
447
request.setUser(loginName);
448             if (log.isDebugEnabled()) {
449                 log.debug("good login for uid: " + uid);
450             }
451
452             // set locale
453
try {
454                 request.getSession().removePersistentAttribute(Messages.LOCALE_KEY);
455                 request.getSession().removePersistentAttribute(Globals.ERROR_KEY);
456                 Messages.establishLocale(hreq);
457             } catch (ServletException JavaDoc se) {
458                 log.error("Cannot manipulate local in session", se);
459
460                 // do not abort entire action since this error is recoverable
461
}
462
463             /* Template method, override in your derived class to do any
464 work you may want to accomplish after a successful login */

465             postLoginProcessing(request, response);
466             String JavaDoc origURL = null;
467             if (session != null) {
468                 SerializableString originalURL = (SerializableString) session.getPersistentAttribute(
469                         ExpressoConstants.CONTROLLER_ORIGINAL_URL_KEY);
470
471                 if (originalURL != null) {
472                     origURL = originalURL.toString();
473                     session.removePersistentAttribute(ExpressoConstants.CONTROLLER_ORIGINAL_URL_KEY);
474                 }
475             }
476             String JavaDoc nextURL = StringUtil.notNull(request.getParameter("next"));
477             if (origURL != null && origURL.length() > 0) {
478
479                 /** redirect to original destination
480                  * BUT be careful to use an HTTP tag redirection
481                  * so that the login cookie can be planted. we cannot
482                  * simply call sendRedirect because then the cookie
483                  * from the current response (set during attemptLogin)
484                  * would not reach the browser. instead, we send a result
485                  * page, which plants the cookie, and that page has a
486                  * redirect tag.
487                  */

488
489                 // provide redirect page with a link to destination in case the browser does
490
// not redirect properly
491
hreq.setAttribute("destination", origURL);
492             } else if (nextURL.length() > 0) {
493                 hreq.setAttribute("destination", nextURL);
494             } else {
495
496                 /**
497                  *
498                  if we got here, someone went directly to login page, so there
499                  was no original "destination" besides the login page.
500                  in that case, send them to a some "home" page,
501                  specified as the forward "home" forward
502                  */

503
504                 // use the previous status.jsp page if we do not find
505
// a "home" global forward specification
506
destination = null;
507
508                 ActionForward fwd = null;
509                 try {
510                     ServletControllerRequest req = (ServletControllerRequest) request;
511                     ForwardConfig fc = req.getMapping().getModuleConfig().findForwardConfig("home");
512                     fwd = new ActionForward(fc.getName(), fc.getPath(),
513                             fc.getRedirect(), fc.getContextRelative());
514                 } catch (Exception JavaDoc e) {
515                     log.error("cannot cast to get servlet request: ", e);
516                 }
517
518                 if (fwd == null) {
519                     log.warn("global forward 'home' is missing using status.jsp");
520                     response.addTransition(new Transition("promptChangePassword",
521                             this));
522                     response.addTransition(new Transition("promptLogin", this));
523                     response.addTransition(new Transition("processLogout", this));
524
525                     Transition editPref = new Transition();
526                     editPref.setName("editPreferences");
527                     editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
528                             com.jcorporate.expresso.services
529
                            .controller.EditUserPreference.class.getName());
530                     editPref.addParam(STATE_PARAM_KEY, "edit");
531                     response.add(editPref);
532
533                     Transition showDBMenu = new Transition();
534                     showDBMenu.setName("showDBMenu");
535                     showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
536                             this.getDefaultRegistrationController()
537                             .getClass().getName());
538                     showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
539                     response.add(showDBMenu);
540
541                 } else {
542                     destination = ConfigManager.getContextPath() +
543                             fwd.getPath();
544
545                     hreq.setAttribute("destination", destination);
546                     if (log.isInfoEnabled()) {
547                         log.info("via redirect.jsp, redirecting to: "
548                                 + destination);
549                     }
550                 }
551             }
552         }
553
554
555         // redirect.jsp actually handles redirect
556
}
557
558     /**
559      * Logs a user out of the system and invalidates their session.
560      *
561      * @param request The framework controller request
562      * @param response The framework ControllerResponse object
563      * @throws ControllerException upon logic error
564      */

565     protected void runProcessLogoutState(ControllerRequest request,
566                                          ControllerResponse response)
567             throws ControllerException {
568         PersistentSession session = request.getSession();
569         String JavaDoc loginName = request.getUser();
570         String JavaDoc successMessage = loginName + " has been logged out";
571
572         if (loginName.equals("")) {
573             successMessage = "You were not logged in anyway!";
574         }
575
576         if (request instanceof ServletControllerRequest) {
577             ServletControllerRequest sreq = (ServletControllerRequest) request;
578             LoginController.setCookie(null, null,
579                     (HttpServletResponse JavaDoc) sreq.getServletResponse(),
580                     true, request.getDataContext());
581
582         }
583         Output successOutput = new Output();
584         successOutput.setName("sucessMessage");
585         successOutput.setContent(successMessage);
586         response.add(successOutput);
587         response.setUser(User.UNKNOWN_USER);
588
589         Transition pr = new Transition("promptSelfRegister", this.getDefaultRegistrationController());
590         pr.addParam("dbContext", request.getDataContext());
591         response.add(pr);
592
593         Transition pl = new Transition("promptLogin", this);
594         pl.addParam("dbContext", request.getDataContext());
595         response.add(pl);
596
597         session.setClientAttribute("UserName", "NONE");
598         session.setClientAttribute("Password", "NONE");
599         session.setClientAttribute("dbContext", "NONE");
600         session.removePersistentAttribute("CurrentLogin");
601         session.invalidate();
602
603         postLogoutProcessing(request, response);
604
605
606     }
607
608     /**
609      * Template Method pattern. override in subclasses as necessary
610      *
611      * @param request The framework controller request
612      * @param response The framework ControllerResponse object
613      */

614     public void postLogoutProcessing(ControllerRequest request, ControllerResponse response)
615             throws ControllerException {
616         // * Template Method pattern. override in subclasses as necessary
617
}
618
619
620     /**
621      * Process the "Please Send me a new password" state.
622      *
623      * @param request The framework controller request
624      * @param response The framework ControllerResponse object
625      * @throws ControllerException upon logic error
626      * @throws NonHandleableException upon fatal error
627      */

628     protected void runProcessSendPasswordState(ControllerRequest request,
629                                                ControllerResponse response)
630             throws ControllerException,
631             NonHandleableException {
632         //
633
//Validate input
634
//
635
ErrorCollection errors = request.getErrorCollection();
636         if (errors == null) {
637             errors = new ErrorCollection();
638         }
639
640
641         String JavaDoc dbContext = StringUtil.notNull(request.getParameter("dbContext"));
642
643         if (!dbContext.equals("")) {
644             request.setDataContext(dbContext);
645         }
646
647         response.add(new Transition("promptSelfRegister", this.getDefaultRegistrationController()));
648         response.add(new Transition("promptLogin", this));
649         String JavaDoc email = StringUtil.replaceAll(StringUtil.notNull(request.getParameter("Email")), "%", "");
650
651         if (email == null || email.length() == 0) {
652             errors.addError("error.login.invalidemail");
653         }
654
655         if (errors.getErrorCount() > 0) {
656             response.saveErrors(errors);
657             transition("promptSendPassword", request, response);
658             return;
659         }
660
661         try {
662             User myUser = new User();
663             myUser.setDataContext(request.getDataContext());
664             myUser.setEmail(email);
665
666             if (!myUser.find()) {
667                 errors.addError("error.login.nouseremailfound");
668             }
669
670             String JavaDoc loginName = myUser.getLoginName();
671
672             if (errors.getErrorCount() < 1) {
673                 if (!myUser.getAccountStatus().equals("A")) {
674                     log.warn("User \"" + loginName +
675                             "\" attempted password reset, denied because account status is \"" +
676                             myUser.getAccountStatus() + "\"");
677                     errors.addError("error.login.accountdiablednosendpaswd");
678                 }
679             }
680             if (errors.getErrorCount() < 1) {
681                 boolean emailValidate = false;
682                 RegistrationDomain rd = null;
683                 rd = new RegistrationDomain();
684                 rd.setDataContext(request.getDataContext());
685                 rd.setField("Name", myUser.getRegistrationDomain());
686
687                 if (!rd.find()) {
688                     throw new ControllerException("Registration domain \"" +
689                             myUser.getRegistrationDomain() +
690                             "\" has not been defined");
691                 }
692                 if (rd.getField("EmailValidate").equals("Y")) {
693                     emailValidate = true;
694                 }
695
696                 /* HACK: Even though registration doesn't require */
697                 /* email validate, passwords *always* do */
698                 emailValidate = true;
699
700                 ServletControllerRequest sparams = (ServletControllerRequest) request;
701                 HttpServletRequest JavaDoc hreq = (HttpServletRequest JavaDoc) sparams.getServletRequest();
702
703                 if (emailValidate) {
704                     String JavaDoc emailAuthCode = myUser.getEmailAuthCode();
705                     myUser.setEmailValCode(emailAuthCode);
706                     myUser.update();
707
708                     try {
709                         ValidationEntry ve = new ValidationEntry(request.getDataContext());
710                         ve.setValidationHandler("com.jcorporate.expresso.services.validation.ChangePasswordValidator");
711                         ve.setTitle("Change Password Validation");
712                         ve.setDesc("user=" + loginName + ", db=" +
713                                 request.getDataContext());
714                         ve.setServer(hreq.getServerName());
715                         ve.setPort(Integer.toString(hreq.getServerPort()));
716                         ve.setContextPath(hreq.getContextPath());
717                         ve.addParam("db", request.getDataContext());
718                         ve.addParam("UserName", loginName);
719                         ve.addParam("LoginController", this.getClass().getName());
720                         ve.submit();
721                     } catch (AuthValidationException avex) {
722                         throw new ControllerException("Validation framework problem",
723                                 avex);
724                     }
725
726                     Output successMessage = new Output("successMessage",
727                             "Email was sent to \"" +
728                             email +
729                             "\" to verify password change request");
730                     response.addOutput(successMessage);
731                 } else {
732                     String JavaDoc password = myUser.randomPassword();
733                     myUser.setPassword(password);
734                     myUser.update();
735
736                     FastStringBuffer msg = FastStringBuffer.getInstance();
737                     msg.append(response.getString("passwdReset",
738                             myUser.getLoginName(),
739                             password,
740                             Setup.getValue(request.getDataContext(),
741                                     "CompanyName"),
742                             Setup.getValue(request.getDataContext(),
743                                     "HomePageURL")));
744                     myUser.notify(response.getString("passwdResetSubject"),
745                             msg.toString());
746                     msg.release();
747                     Output successMessage = new Output("successMessage",
748                             "Password for \"" +
749                             email +
750                             "\" was reset and an email sent");
751                     response.addOutput(successMessage);
752                 }
753             }
754         } catch (Exception JavaDoc dbe) {
755             throw new ControllerException(dbe);
756         } finally {
757             if (errors.getErrorCount() < 1) {
758                 response.clearFormCache();
759             } else {
760                 response.saveErrors(errors);
761                 response.setFormCache();
762                 transition("promptSendPassword", request, response);
763                 return;
764             }
765         }
766     }
767
768     /**
769      * Displays the 'change password' page.
770      *
771      * @param request The framework controller request
772      * @param response The framework ControllerResponse object
773      * @throws ControllerException upon logic error
774      */

775     protected void runPromptChangePasswordState(ControllerRequest request,
776                                                 ControllerResponse response)
777             throws ControllerException {
778         response.clearFormCache();
779
780         Input oldPassword = new Input();
781         oldPassword.setName("oldPassword");
782         oldPassword.setLabel(response.getString("CurrentPassword"));
783
784         String JavaDoc opw = StringUtil.notNull(response.getFormCache("oldPassword"));
785         oldPassword.setDefaultValue(opw);
786         oldPassword.setDisplayLength(15);
787         oldPassword.setMaxLength(30);
788         oldPassword.setType("password");
789         response.addInput(oldPassword);
790
791         Input password = new Input();
792         password.setName("Password");
793         password.setLabel(response.getString("NewPassword"));
794
795         String JavaDoc pw = StringUtil.notNull(response.getFormCache("Password"));
796         password.setDefaultValue(pw);
797         password.setDisplayLength(15);
798         password.setMaxLength(30);
799         password.setType("password");
800         response.addInput(password);
801
802         Input password_verify = new Input();
803         password_verify.setName("password_verify");
804         password_verify.setLabel(response.getString("RetypePassword"));
805
806         String JavaDoc pwv = StringUtil.notNull(response.getFormCache("password_verify"));
807         password_verify.setDefaultValue(pwv);
808         password_verify.setDisplayLength(15);
809         password_verify.setMaxLength(30);
810         password_verify.setType("password");
811         response.addInput(password_verify);
812
813         //Transition change = new Transition(response.getString("changePasswordTitle"), this);
814
Transition change = new Transition("processChangePassword", this);
815         change.setLabel(response.getString("changePasswordTitle"));
816         response.add(change);
817         response.addTransition(new Transition("promptChangePassword", this));
818         response.addTransition(new Transition("promptLogin", this));
819         response.addTransition(new Transition("processLogout", this));
820
821         Transition editPref = new Transition();
822         editPref.setName("editPreferences");
823         editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
824                 "com.jcorporate.expresso.services.controller.EditUserPreference");
825         editPref.addParam(STATE_PARAM_KEY, "edit");
826         response.add(editPref);
827
828         Transition showDBMenu = new Transition();
829         showDBMenu.setName("showDBMenu");
830         showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
831                 this.getDefaultRegistrationController().getClass().getName());
832         showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
833         response.add(showDBMenu);
834     }
835
836     /**
837      * Prompts the user for login.
838      *
839      * @param request The ControllerRequest object
840      * @param response The ControllerResponse object
841      */

842     protected void runPromptLoginState(ControllerRequest request,
843                                        ControllerResponse response)
844             throws ControllerException {
845         PersistentSession session = request.getSession();
846         Input dbContext = new Input("dbContext");
847         String JavaDoc useDB = StringUtil.notNull(request.getParameter("dbContext"));
848
849         if (!useDB.equals("")) {
850             request.setDataContext(useDB);
851             response.addOutput(new Output("dbContext", useDB));
852         } else {
853             dbContext.setDefaultValue(request.getDataContext());
854             dbContext.setLabel(response.getString("Context/Database_"));
855
856             String JavaDoc oneConfigKey = null;
857             String JavaDoc oneDescrip = null;
858             Vector JavaDoc v = new Vector JavaDoc();
859
860             for (Enumeration JavaDoc ie = ConfigManager.getAllConfigKeys();
861                  ie.hasMoreElements();) {
862                 oneConfigKey = (String JavaDoc) ie.nextElement();
863                 oneDescrip = "";
864
865                 try {
866                     oneDescrip = StringUtil.notNull(ConfigManager.getContext(oneConfigKey).getDescription());
867
868                     if (oneDescrip.equals("")) {
869                         oneDescrip = oneConfigKey;
870                     }
871                     /* If it's not an expresso context, you can't log in to it */
872                     if (ConfigManager.getContext(oneConfigKey).hasSetupTables()) {
873                         v.addElement(new ValidValue(oneConfigKey, oneDescrip));
874                     }
875                 } catch (ConfigurationException ce) {
876                     throw new ControllerException(ce);
877                 }
878             }
879
880             dbContext.setValidValues(v);
881             response.addInput(dbContext);
882         }
883
884         // Fill in the Login field with values in following priority: form-cache, cookie
885
Input loginName = new Input();
886         loginName.setName("LoginName");
887
888         String JavaDoc ln = StringUtil.notNull(response.getFormCache("LoginName"));
889
890         if (ln.equals("")) {
891             ln = request.getUser();
892         }
893         if (ln.equals(User.UNKNOWN_USER)) {
894             ln = "";
895         }
896
897         loginName.setDefaultValue(ln);
898         loginName.setDisplayLength(15);
899         loginName.setMaxLength(30);
900         loginName.setLabel("Login");
901         response.addInput(loginName);
902
903         // Fill in the Password field with values in following priority: form-cache, cookie
904
Input password = new Input();
905         password.setName("Password");
906         password.setLabel("Password");
907
908         String JavaDoc pw = StringUtil.notNull(response.getFormCache("Password"));
909
910         if ("".equals(pw)) {
911             pw = StringUtil.notNull(session.getClientAttribute("Password"));
912         }
913
914         if ("NONE".equals(pw)) {
915             pw = "";
916         }
917
918         password.setDefaultValue(pw);
919         password.setDisplayLength(15);
920         password.setMaxLength(30);
921         password.setType("password");
922         response.addInput(password);
923
924         // Fill in the Remember field
925
Input remember = new Input("Remember");
926         remember.setLabel("Remember Login");
927
928         String JavaDoc rm = response.getFormCache("Remember");
929
930         if (rm == null || rm.length() == 0) {
931             rm = "Y";
932         }
933
934         remember.setType("checkbox");
935         remember.setDefaultValue(rm);
936         response.addInput(remember);
937
938         //
939
//Put a hidden element on the form to pass the next parameter
940
//to process
941
//
942
String JavaDoc oneParam = StringUtil.notNull(request.getParameter("next"));
943
944         if (oneParam.length() > 0) {
945             Input nextURL = new Input("next");
946             nextURL.setType("hidden");
947             nextURL.setDefaultValue(oneParam);
948             response.addInput(nextURL);
949         }
950
951         oneParam = StringUtil.notNull(request.getParameter("immediate"));
952
953         if (oneParam.length() > 0) {
954             Input nextURL = new Input("immediate");
955             nextURL.setType("hidden");
956             nextURL.setDefaultValue(oneParam);
957             response.addInput(nextURL);
958         }
959
960         Transition login = new Transition("processLogin", this);
961
962         if (!useDB.equals("")) {
963             login.addParam("dbContext", useDB);
964         }
965
966         response.add(login);
967
968         Transition promptChangePassword = new Transition("promptChangePassword", this);
969
970         if (!useDB.equals("")) {
971             promptChangePassword.addParam("dbContext", useDB);
972         }
973
974         response.add(promptChangePassword);
975         response.add(new Transition("processLogout", this));
976
977         Transition promptSendPassword = new Transition("promptSendPassword",
978                 this);
979
980         if (!useDB.equals("")) {
981             promptSendPassword.addParam("dbContext", useDB);
982         }
983
984         response.add(promptSendPassword);
985         String JavaDoc registerController = this.getDefaultRegistrationController().getClass().getName();
986
987
988         if (registerController != null) {
989             Transition promptRegister = new Transition();
990             promptRegister.setControllerObject(registerController);
991             promptRegister.setState("promptSelfRegister");
992             promptRegister.setName("promptRegister");
993
994             if (!useDB.equals("")) {
995                 promptRegister.addParam("dbContext", useDB);
996             } else {
997                 promptRegister.addParam("dbContext", "default");
998             }
999
1000            response.add(promptRegister);
1001        }
1002
1003        Transition promptLogin = new Transition("promptLogin", this);
1004
1005        if (!useDB.equals("")) {
1006            promptLogin.addParam("dbContext", useDB);
1007        }
1008
1009        response.add(promptLogin);
1010
1011        Transition showDBMenu = new Transition();
1012        showDBMenu.setName("showDBMenu");
1013        showDBMenu.addParam(Controller.CONTROLLER_PARAM_KEY,
1014                this.getDefaultRegistrationController().getClass().getName());
1015        showDBMenu.addParam(STATE_PARAM_KEY, "showDBMenu");
1016        response.add(showDBMenu);
1017
1018        Transition editPref = new Transition();
1019        editPref.setName("editPreferences");
1020        editPref.addParam(Controller.CONTROLLER_PARAM_KEY,
1021                "com.jcorporate.expresso.services.controller.EditUserPreference");
1022        editPref.addParam(STATE_PARAM_KEY, "edit");
1023        response.add(editPref);
1024
1025        //
1026
//Add a revalidate email link to the login screen if the default
1027
//registration domain sends validation emails.
1028
//
1029
try {
1030            String JavaDoc regDomain = Setup.getValue(request.getDataContext(), "defaultRegDomain");
1031            if (regDomain != null && regDomain.length() > 0) {
1032                RegistrationDomain rd = new RegistrationDomain(Securable.SYSTEM_ACCOUNT);
1033                rd.setDataContext(request.getDataContext());
1034                rd.setField("Name", regDomain);
1035                if (rd.find()) {
1036                    String JavaDoc emailValidate = rd.getField("EmailValidate");
1037                    if (StringUtil.toBoolean(emailValidate)) {
1038                        Transition revalidate = new Transition("promptRevalidate", this);
1039                        revalidate.setLabel("Resend Email Validation");
1040                        response.add(revalidate);
1041                    }
1042                }
1043            }
1044        } catch (DBException ex) {
1045            log.error("Error getting default regdomain setup parameter", ex);
1046        }
1047    }
1048
1049    /**
1050     * This function prompts for email revalidation
1051     *
1052     * @param request The <code>ControllerRequest</code> object handed to us
1053     * by the framework.
1054     * @param response The <code>ControllerResponse</code> object handed to us
1055     * by the framework
1056     * @throws ControllerException upon error
1057     */

1058    protected void runPromptRevalidateState(ControllerRequest request,
1059                                            ControllerResponse response) throws ControllerException {
1060        response.setTitle("Enter Email For Revalidation Request");
1061
1062        response.addOutput(new Output("If there was a transient error in the email delivery" +
1063                " system, you can request a resend of your email validation request."));
1064
1065        Input i = new Input("Email", "Email Address");
1066        response.add(i);
1067
1068        Transition t = new Transition("processRevalidate", this);
1069        t.setLabel("Resend Validation Email");
1070        response.add(t);
1071    }
1072
1073    /**
1074     * This function processes the revalidation email request, attempts to
1075     * find the user, and if successfull, forwards the control over to the
1076     * RegistrationController to do the actual resending of the validation
1077     * email.
1078     *
1079     * @param request The <code>ControllerRequest</code> object handed to us
1080     * by the framework.
1081     * @param response The <code>ControllerResponse</code> object handed to us
1082     * by the framework
1083     * @throws ControllerException upon error
1084     * @throws NonHandleableException upon fatal error
1085     */

1086    protected void runProcessRevalidateState(ControllerRequest request,
1087                                             ControllerResponse response)
1088            throws ControllerException, NonHandleableException {
1089        response.setTitle("Revalidation Processing");
1090        ErrorCollection ec = request.getErrorCollection();
1091        if (ec == null) {
1092            ec = new ErrorCollection();
1093        }
1094
1095        if (ec.getErrorCount() > 0) {
1096            response.setFormCache();
1097            response.saveErrors(ec);
1098            transition("promptRevalidate", request, response);
1099            return;
1100        }
1101
1102        try {
1103            User u = new User();
1104            u.setDBName(request.getDataContext());
1105            u.setEmail(request.getParameter("Email"));
1106            if (!u.find()) {
1107                log.error("Received request for email address: "
1108                        + request.getParameter("Email") +
1109                        "but user does not exist");
1110
1111                ec.addError("You entered an invalid email address");
1112            } else if (!"I".equals(u.getAccountStatus())) {
1113                ec.addError("This account is not waiting for email address confirmation");
1114            }
1115
1116            if (ec.getErrorCount() > 0) {
1117                response.setFormCache();
1118                response.saveErrors(ec);
1119                transition("promptRevalidate", request, response);
1120            } else {
1121                Transition reValidate = new Transition("revalidate",
1122                        "Click Here To Resend Email Validation",
1123                        this.getDefaultRegistrationController().getClass(), "processRevalidate");
1124
1125                reValidate.addParam("Email", u.getEmail());
1126                reValidate.addParam("db", request.getDataContext());
1127                reValidate.addParam("loginController", this.getClass().getName());
1128                reValidate.transition(request, response, false);
1129            }
1130
1131
1132        } catch (DBException ex) {
1133            log.error("Error processing email revalidation", ex);
1134            throw new ControllerException("Error processing email revalidation." +
1135                    " The Administrator has been notified");
1136        }
1137
1138    }
1139
1140
1141    protected void runPromptSendPasswordState(ControllerRequest request,
1142                                              ControllerResponse response)
1143            throws ControllerException {
1144        String JavaDoc dbContext = StringUtil.notNull(request.getParameter("dbContext"));
1145
1146        if (!dbContext.equals("")) {
1147            request.setDataContext(dbContext);
1148        }
1149
1150        Input email = new Input();
1151        email.setName("Email");
1152        email.setLabel("EMail");
1153
1154        String JavaDoc emailValue = StringUtil.notNull(response.getFormCache("Email"));
1155        email.setDefaultValue(emailValue);
1156        email.setDisplayLength(45);
1157        email.setMaxLength(60);
1158        response.addInput(email);
1159
1160        Transition submit = new Transition("processSendPassword", this);
1161        submit.setLabel(response.getString("passwdResetSubject"));
1162        submit.addParam("dbContext", request.getDataContext());
1163        response.add(submit);
1164
1165        Transition pr = new Transition("promptSelfRegister", this.getDefaultRegistrationController());
1166        pr.addParam("dbContext", request.getDataContext());
1167        response.add(pr);
1168
1169        Transition pl = new Transition("promptLogin", this);
1170        pl.addParam("dbContext", request.getDataContext());
1171        response.add(pl);
1172    }
1173
1174    /**
1175     * Override the normal stateAllowed method to always allow
1176     * access to this controller for certain states - otherwise no-one can ever log in :-)
1177     *
1178     * @param newState the state to transition to.
1179     * @param params The controllerRequest object
1180     * @return true if the state is allowed for the currently logged in user.
1181     * @throws ControllerException if there is an error while looking up the sercurity permissions
1182     */

1183    public synchronized boolean stateAllowed(String JavaDoc newState,
1184                                             ControllerRequest params)
1185            throws ControllerException {
1186        if (newState.equals("promptChangePW") ||
1187                newState.equals("processChangePW") ||
1188                newState.equals("promptLogout")) {
1189            return super.stateAllowed(newState, params);
1190        }
1191
1192        return true;
1193    } /* stateAllowed(String) */
1194
1195
1196}
Popular Tags