001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata groupware may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: LoginAction.java,v $
031: * Revision 1.5 2005/10/14 14:37:36 colinmacleod
032: * Confused? Changed ActionMessages back to ActionErrors.
033: *
034: * Revision 1.4 2005/10/11 18:57:17 colinmacleod
035: * Fixed some checkstyle and javadoc issues.
036: *
037: * Revision 1.3 2005/10/03 10:21:15 colinmacleod
038: * Fixed some style and javadoc issues.
039: *
040: * Revision 1.2 2005/10/02 14:08:58 colinmacleod
041: * Added/improved log4j logging.
042: *
043: * Revision 1.1 2005/09/29 13:06:05 colinmacleod
044: * First version of setting subproject.
045: * Existing classes restructured, new setting user interface created.
046: * Flexible XML UI configuration makes it easy to reuse the same web pages in
047: * other projects.
048: * Web files work as stand-alone webapp for testing.
049: *
050: * Revision 1.6 2005/09/14 15:57:47 colinmacleod
051: * Made database paths more flexible, to suit ivata cms.
052: * Removed unused local and class variables.
053: * Added serialVersionUID.
054: *
055: * Revision 1.5 2005/04/22 10:27:23 colinmacleod
056: * Changed to using hibernate properties
057: * rather than the hibernate configuration
058: * instance directly.
059: *
060: * Revision 1.4 2005/04/10 19:38:22 colinmacleod
061: * Updated login pages to change theme.
062: *
063: * Revision 1.3 2005/04/09 17:19:57 colinmacleod
064: * Changed copyright text to GPL v2 explicitly.
065: *
066: * Revision 1.2 2005/03/16 15:55:43 colinmacleod
067: * Changed debug logging for no java script to info.
068: *
069: * Revision 1.1.1.1 2005/03/10 17:51:40 colinmacleod
070: * Restructured ivata op around Hibernate/PicoContainer.
071: * Renamed ivata groupware.
072: *
073: * Revision 1.6 2004/12/31 18:27:44 colinmacleod
074: * Added MaskFactory to constructor of MaskAction.
075: *
076: * Revision 1.5 2004/12/23 20:50:58 colinmacleod
077: * Split off guest login from LoginAction into a new action.
078: *
079: * Revision 1.4 2004/11/12 18:19:16 colinmacleod
080: * Change action and form classes to extend MaskAction, MaskForm respectively.
081: *
082: * Revision 1.3 2004/11/12 15:57:19 colinmacleod
083: * Removed dependencies on SSLEXT.
084: * Moved Persistence classes to ivata masks.
085: *
086: * Revision 1.2 2004/11/03 15:31:51 colinmacleod
087: * Change method interfaces to remove log.
088: *
089: * Revision 1.1 2004/09/30 15:15:59 colinmacleod
090: * Split off addressbook elements into security subproject.
091: *
092: * Revision 1.7 2004/07/19 21:58:35 colinmacleod
093: * Changed Vector to List where possible.
094: *
095: * Revision 1.6 2004/07/18 16:16:55 colinmacleod
096: * Added checking that the form is present, and of the right class.
097: *
098: * Revision 1.5 2004/07/13 19:41:12 colinmacleod
099: * Moved project to POJOs from EJBs.
100: * Applied PicoContainer to services layer (replacing session EJBs).
101: * Applied Hibernate to persistence layer (replacing entity EJBs).
102: *
103: * Revision 1.4 2004/03/21 21:16:05 colinmacleod
104: * Shortened name to ivata op.
105: *
106: * Revision 1.3 2004/03/21 20:20:54 colinmacleod
107: * Changed session variable called mailSession to securityServerSession.
108: *
109: * Revision 1.2 2004/02/01 22:00:32 colinmacleod
110: * Added full names to author tags
111: *
112: * Revision 1.1.1.1 2004/01/27 20:57:45 colinmacleod
113: * Moved ivata openportal to SourceForge..
114: *
115: * Revision 1.5 2003/11/13 16:03:15 jano
116: * commitng everything to CVS
117: * can deploy and application is ruuning, can login into
118: *
119: * Revision 1.4 2003/11/07 14:54:15 jano
120: * commitng after fixing some bugs
121: *
122: * Revision 1.3 2003/10/24 13:18:12 jano
123: * fixing some bugs
124: *
125: * Revision 1.2 2003/10/17 12:36:12 jano
126: * fixing problems with building
127: * converting intranet -> portal
128: * Eclipse building
129: *
130: * Revision 1.1.1.1 2003/10/13 20:50:07 colin
131: * Restructured portal into subprojects
132: *
133: * Revision 1.7 2003/07/05 15:57:25 colin
134: * Added possibility for empty jndiPrefix = root default context
135: *
136: * Revision 1.6 2003/03/14 10:26:06 jano
137: * adding backdoor man functionality
138: * backdoor man = briezky
139: *
140: * Revision 1.5 2003/03/12 14:31:53 peter
141: * fixed jndiPrefix handling - one webapp problem
142: *
143: * Revision 1.4 2003/03/11 18:25:45 colin
144: * changes to allow just one webapp
145: *
146: * Revision 1.3 2003/03/05 15:16:48 colin
147: * fixed jndiPrefix to request.getContextPath
148: *
149: * Revision 1.2 2003/02/27 12:03:16 colin
150: * changed forward to redirect to avoid displaying the parameters in the browser
151: *
152: * Revision 1.1 2003/02/24 18:53:57 colin
153: * added to admin
154: *
155: * Revision 1.5 2003/02/06 12:41:22 colin
156: * changed checks for null to checks for isNullOrEmpty (login, forward)
157: *
158: * Revision 1.4 2003/02/06 12:22:25 colin
159: * changed from errors() to isErrors() (a la struts 1.1c)
160: *
161: * Revision 1.3 2003/02/04 17:38:14 colin
162: * updated for new execute interface
163: *
164: * Revision 1.2 2003/01/27 08:59:12 colin
165: * simplified version of login with keepAlive.jsp
166: *
167: * Revision 1.1 2003/01/18 20:29:42 colin
168: * converted login process to struts
169: * added checking for javascript at login
170: * -----------------------------------------------------------------------------
171: */
172: package com.ivata.groupware.admin.security.struts;
173:
174: import java.lang.reflect.InvocationTargetException;
175: import java.util.Properties;
176:
177: import javax.servlet.http.HttpServletRequest;
178: import javax.servlet.http.HttpServletResponse;
179: import javax.servlet.http.HttpSession;
180:
181: import org.apache.commons.beanutils.PropertyUtils;
182: import org.apache.log4j.Logger;
183: import org.apache.struts.action.ActionErrors;
184: import org.apache.struts.action.ActionForm;
185: import org.apache.struts.action.ActionForward;
186: import org.apache.struts.action.ActionMapping;
187: import org.apache.struts.action.ActionMessage;
188: import org.apache.struts.action.ActionMessages;
189: import org.apache.struts.util.RequestUtils;
190: import org.picocontainer.PicoContainer;
191: import org.sourceforge.clientsession.ClientSession;
192:
193: import com.ivata.groupware.admin.security.Security;
194: import com.ivata.groupware.admin.security.server.SecuritySession;
195: import com.ivata.groupware.admin.security.user.UserDO;
196: import com.ivata.groupware.admin.setting.Settings;
197: import com.ivata.groupware.container.PicoContainerFactory;
198: import com.ivata.groupware.container.persistence.hibernate.HibernateSetupConstants;
199: import com.ivata.mask.MaskFactory;
200: import com.ivata.mask.persistence.FinderException;
201: import com.ivata.mask.util.StringHandling;
202: import com.ivata.mask.util.SystemException;
203: import com.ivata.mask.web.browser.Browser;
204: import com.ivata.mask.web.struts.MaskAction;
205: import com.ivata.mask.web.struts.MaskAuthenticator;
206: import com.ivata.mask.web.tag.theme.ThemeConstants;
207:
208: /**
209: * <p>This <code>Action</code> is invoked whenever someone tries to
210: * login to the intranet system.</p>
211: *
212: * @since 2003-01-15
213: * @author Colin MacLeod
214: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
215: * @version $Revision: 1.5 $
216: */
217: public class LoginAction extends MaskAction {
218: /**
219: * <p>
220: * Log4j logger for, well, logging.
221: * </p>
222: */
223: private static final Logger logger = Logger
224: .getLogger(LoginAction.class);
225: /**
226: * Theme name which means the user wants to use the same theme as last time.
227: */
228: public static final String USE_LAST_THEME = "last";
229: /**
230: * <copyDoc>Refer to {@link LoginAction#LoginAction}.</copyDoc>
231: */
232: private Security security;
233:
234: /**
235: * <copyDoc>Refer to {@link LoginAction#LoginAction}.</copyDoc>
236: */
237: private Settings settings;
238:
239: /**
240: * Constructor. Normally called by <code>PicoContainer</code>.
241: *
242: * @param securityParam The system security interface is responsible for
243: * actually logging the user in.
244: * @param settingsParam Used to retrieve site settings for default database
245: * name, default forward, default theme.
246: * @param maskFactory {@inheritDoc}
247: * @param authenticator {@inheritDoc}
248: */
249: public LoginAction(final Security securityParam,
250: final Settings settingsParam,
251: final MaskFactory maskFactory,
252: final MaskAuthenticator authenticator) {
253: super (maskFactory, authenticator);
254: this .security = securityParam;
255: this .settings = settingsParam;
256: }
257:
258: /**
259: * Private helper. Called when the user doesn't have JavaScript enabled, to
260: * find a suitable message for the user's browser.
261: *
262: * @param browser Newly created browser indicating site user's viewing
263: * capabilities. The error message is tailored to this browser.
264: * @param errors All processing errors to date. Appropriate JavaScript
265: * error will be added to this collection.
266: */
267: private void addJavaScriptError(final Browser browser,
268: final ActionMessages errors) {
269: if (logger.isInfoEnabled()) {
270: logger.info("Javascript is unavailable on user's browser.");
271: }
272: // if you don't have javascript, we show a special login designed
273: // to help you activate (and check it is working)
274: String errorKey;
275:
276: if (browser.isInternetExplorer()) {
277: if (browser.getVersion().compareTo("5") >= 0) {
278: if (logger.isDebugEnabled()) {
279: logger.debug("Identified IE5 browser.");
280: }
281: // they changed the place for javascript preferences. Grrr.
282: errorKey = "login.error.javascript.iexplore5";
283: } else {
284: if (logger.isDebugEnabled()) {
285: logger.debug("Identified IE browser.");
286: }
287: errorKey = "login.error.javascript.iexplore";
288: }
289: } else if (browser.isFirefox()) {
290: if (logger.isDebugEnabled()) {
291: logger.debug("Identified Firefox browser.");
292: }
293: // error key is different for windows
294: if (System.getProperty("os.name").toLowerCase().indexOf(
295: "windows") == -1) {
296: errorKey = "login.error.javascript.firefox";
297: } else {
298: errorKey = "login.error.javascript.firefox.windows";
299: }
300: } else if (browser.isNetscape() || browser.isMozilla()) {
301: if (logger.isDebugEnabled()) {
302: logger.debug("Identified Netscape/Mozilla browser.");
303: }
304: errorKey = "login.error.javascript.netscape";
305: } else if (browser.isOpera()) {
306: if (browser.getVersion().compareTo("6") >= 0) {
307: // they changed the place for javascript preferences. Grrr.
308: errorKey = "login.error.javascript.opera6";
309: if (logger.isDebugEnabled()) {
310: logger.debug("Identified Opera 6 browser.");
311: }
312: } else {
313: errorKey = "login.error.javascript.opera";
314: if (logger.isDebugEnabled()) {
315: logger.debug("Identified Opera browser.");
316: }
317: }
318: } else {
319: errorKey = "login.error.javascript.unknown";
320: if (logger.isDebugEnabled()) {
321: logger.debug("Could not identify browser.");
322: }
323: }
324: errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
325: errorKey));
326: }
327:
328: /**
329: * <p>Overrides and extends (calls) the super class implementation to
330: * tell it not to check the session.</p>
331: *
332: * @param mapping The ActionMapping used to select this instance.
333: * @param form The optional ActionForm bean for this request (if any).
334: * @param request The non-HTTP request we are processing.
335: * @param response The non-HTTP response we are creating.
336: * @exception Exception if the application business logic throws
337: * an exception.
338: * @return this method returns a <code>"success"</code>
339: * <code>ActionForward</code> if the compose session is cancelled or
340: * successfully sent, otherwise a <code>"failure"</code>
341: * <code>ActionForward</code>.
342: *
343: */
344: public ActionForward execute(final ActionMapping mapping,
345: final ActionForm form, final HttpServletRequest request,
346: final HttpServletResponse response) throws Exception {
347: if (logger.isDebugEnabled()) {
348: logger.debug("execute(ActionMapping mapping = " + mapping
349: + ", ActionForm form = " + form
350: + ", HttpServletRequest request = " + request
351: + ", HttpServletResponse response = " + response
352: + ") - start");
353: }
354:
355: // this prevents us always going around in circles!!
356: setLogin(true);
357: ActionForward returnActionForward = super .execute(mapping,
358: form, request, response);
359: if (logger.isDebugEnabled()) {
360: logger.debug("execute - end - return value = "
361: + returnActionForward);
362: }
363: return returnActionForward;
364: }
365:
366: /**
367: * <p>Overridden from the default intranet implementation to
368: * manipulate user login.</p>
369: *
370: * @param mapping {@inheritDoc}
371: * @param formParam {@inheritDoc}
372: * @param request {@inheritDoc}
373: * @param response {@inheritDoc}
374: * @param session {@inheritDoc}
375: * @param clientSession {@inheritDoc}
376: * @exception SystemException if there is any problem which
377: * prevents processing. It will result in the webapp being forwarded
378: * to
379: * the standard error page.
380: * @return this method returns the string used to identify the correct
381: * <em>Struts</em> <code>ActionForward</code> which should follow this
382: * page, or <code>null</code> if it should return to the input.
383: */
384: public String execute(final ActionMapping mapping,
385: final ActionForm formParam,
386: final HttpServletRequest request,
387: final HttpServletResponse response,
388: final HttpSession session, final ClientSession clientSession)
389: throws SystemException {
390: if (logger.isDebugEnabled()) {
391: logger.debug("execute(ActionMapping mapping = " + mapping
392: + ", ActionForm formParam = " + formParam
393: + ", HttpServletRequest request = " + request
394: + ", HttpServletResponse response = " + response
395: + ", HttpSession session = " + session
396: + ", ClientSession clientSession = "
397: + clientSession + ") - start");
398: }
399:
400: ActionForm form = formParam;
401: String login = null;
402: SecuritySession securitySession = (SecuritySession) session
403: .getAttribute("securitySession");
404:
405: // the value for the forward changes if there is no javascript
406: String errorForward = "login";
407: if ((form == null) || (securitySession == null)) {
408: if (logger.isDebugEnabled()) {
409: logger
410: .debug("execute - end - return value = loginGuestAction");
411: }
412: return "loginGuestAction";
413: }
414:
415: if (isDefaultDatabase(securitySession)) {
416: if (logger.isDebugEnabled()) {
417: logger
418: .debug("execute - end - return value = setupAction");
419: }
420: return "setupAction";
421: }
422:
423: try {
424: login = (String) PropertyUtils.getSimpleProperty(form,
425: "login");
426: } catch (InvocationTargetException e) {
427: logger.error("execute - error getting login property.", e);
428: throw new SystemException(e);
429: } catch (IllegalAccessException e) {
430: logger.error("execute - error getting login property.", e);
431: throw new SystemException(e);
432: } catch (NoSuchMethodException e) {
433: logger.error("execute - error getting login property.", e);
434: // if any of the methods are missing, it must be the wrong form...
435: form = RequestUtils.createActionForm(request, mapping,
436: mapping.getModuleConfig(), servlet);
437: }
438: // we can't do anything if we don't even have guest access yet
439: if (securitySession == null) {
440: if (logger.isDebugEnabled()) {
441: logger
442: .debug("execute - end - return value = loginGuestAction");
443: }
444: return "loginGuestAction";
445: }
446:
447: // try to find from setting defaultForward
448: UserDO user = initializeUser(request, form);
449: if (user == null) {
450: // set login null to login as guest
451: login = null;
452: }
453: // if the user just changed the theme, use the one specified and go back
454: // again
455: if (StringHandling.isNullOrEmpty(login)) {
456: if (logger.isDebugEnabled()) {
457: logger.debug("execute - end - return value = login");
458: }
459: return "login";
460: }
461:
462: ActionErrors errors = new ActionErrors();
463: String forward = initializeForward(request, user, form, mapping);
464: if (forward == null) {
465: return null;
466: }
467:
468: Browser browser = initializeBrowser(request, form);
469:
470: // this is where we actually try to login
471: securitySession = login(session, form, user, errors);
472:
473: // if there is no javascript on the browser, handle that - if the
474: // settings tell us it is mandatory
475: Boolean requireJavaScript = settings.getBooleanSetting(
476: securitySession, "siteRequireJavaScript", null);
477: assert (requireJavaScript != null) : "Setting 'siteRequireJavaScript' is missing.";
478: if (requireJavaScript.booleanValue()
479: && !browser.isJavaScriptEnabled()) {
480: errorForward = "loginJavaScript";
481: addJavaScriptError(browser, errors);
482: }
483:
484: // if there are errors, you can't get in!
485: if (!errors.isEmpty()) {
486: if (logger.isInfoEnabled()) {
487: logger.info("Errors found for user '" + user.getName()
488: + "'.");
489: }
490: errors.add(ActionMessages.GLOBAL_MESSAGE,
491: new ActionMessage("login.error.login"));
492: saveErrors(request, (ActionMessages) errors);
493: saveToken(request);
494: return errorForward;
495: }
496: if (logger.isInfoEnabled()) {
497: logger.info("Login successful for user '" + user.getName()
498: + "'.");
499: }
500: // if we got here, that means we now have a logged in user
501: session.setAttribute("userName", user.getName());
502: request.setAttribute("loginForward", forward);
503:
504: // if the user changed the theme, save it in the settings for the next
505: // time
506: if (!USE_LAST_THEME.equals(request.getParameter("theme"))) {
507: settings.amendSetting(securitySession, "siteTheme", session
508: .getAttribute(ThemeConstants.ATTRIBUTE_THEME_NAME),
509: user);
510: }
511:
512: if (logger.isDebugEnabled()) {
513: logger.debug("execute - end - return value = " + forward);
514: }
515: return forward;
516: }
517:
518: /**
519: * Create the browser based on the user JavaScript level and
520: * "User-Agent".
521: *
522: * @param request Current servlet request we are processing.
523: * @param form <em>Struts</em> form we are processing.
524: * @return <code>Browser</code>, representing the model and capabilities
525: * of the user's web browser.
526: * @throws SystemException If the <code>javaScriptVersion</code> property
527: * cannot be read from the form.
528: */
529: private Browser initializeBrowser(final HttpServletRequest request,
530: final ActionForm form) throws SystemException {
531: String javaScriptVersion = null;
532: try {
533: javaScriptVersion = (String) PropertyUtils
534: .getSimpleProperty(form, "javaScriptVersion");
535: } catch (InvocationTargetException e) {
536: logger.error("execute - error getting javaScriptVersion.",
537: e);
538: throw new SystemException(e);
539: } catch (IllegalAccessException e) {
540: logger.error("execute - error getting javaScriptVersion.",
541: e);
542: throw new SystemException(e);
543: } catch (NoSuchMethodException e) {
544: logger.error("execute - error getting javaScriptVersion.",
545: e);
546: throw new SystemException(e);
547: }
548: // initialize the browser object
549: if ((javaScriptVersion != null)
550: && javaScriptVersion.trim().equals("")) {
551: javaScriptVersion = null;
552: }
553: Browser browser = new Browser(request.getHeader("User-Agent"),
554: javaScriptVersion);
555: request.getSession().setAttribute("browser", browser);
556: return browser;
557: }
558:
559: /**
560: * Work out which page we should forward to and set it back to the form. If
561: * the user has already chosen a forward, use that, otherwise get the
562: * default forward from the system settings.
563: *
564: * @param request Current servlet request we are processing.
565: * @param user Used to retrieve the default forward, if the
566: * forward was not set in the form.
567: * @param form Current login form we are processing.
568: * @param mapping <em>Struts</em> action mapping.
569: * @return Name of the forward on success, otherwise <code>null</code>.
570: * @throws SystemException If the property cannot be set in the form.
571: */
572: private String initializeForward(final HttpServletRequest request,
573: final UserDO user, final ActionForm form,
574: final ActionMapping mapping) throws SystemException {
575: if (logger.isDebugEnabled()) {
576: logger.debug("setForward() - start");
577: }
578: SecuritySession securitySession = (SecuritySession) request
579: .getSession().getAttribute("securitySession");
580:
581: String forward;
582: try {
583: forward = (String) PropertyUtils.getSimpleProperty(form,
584: "forward");
585: } catch (IllegalAccessException e2) {
586: logger
587: .error(
588: "setForward() - error getting forward property from form.",
589: e2);
590: throw new SystemException(e2);
591: } catch (InvocationTargetException e2) {
592: logger
593: .error(
594: "setForward() - error getting forward property from form.",
595: e2);
596: throw new SystemException(e2);
597: } catch (NoSuchMethodException e2) {
598: logger
599: .error(
600: "setForward() - error getting forward property from form.",
601: e2);
602: throw new SystemException(e2);
603: }
604: if (StringHandling.isNullOrEmpty(forward)) {
605: try {
606: forward = settings.getStringSetting(securitySession,
607: "siteDefaultForward", user);
608: } catch (SystemException e) {
609: logger.error("setForward - error getting setting '"
610: + "siteDefaultForward' for user " + user, e);
611: throw e;
612: }
613: }
614:
615: try {
616: PropertyUtils.setSimpleProperty(form, "forward", forward);
617: } catch (NoSuchMethodException e) {
618: logger
619: .error(
620: "setForward - error setting property 'forward' from form",
621: e);
622: // send the user back to the login page - this form is no use!
623: ActionForm newForm = RequestUtils.createActionForm(request,
624: mapping, mapping.getModuleConfig(), servlet);
625: try {
626: PropertyUtils.setSimpleProperty(newForm, "forward",
627: forward);
628: } catch (IllegalAccessException e1) {
629: logger
630: .error(
631: "setForward - error setting property 'forward' from form",
632: e1);
633: } catch (InvocationTargetException e1) {
634: logger
635: .error(
636: "setForward - error setting property 'forward' from form",
637: e1);
638: } catch (NoSuchMethodException e1) {
639: logger
640: .error(
641: "setForward - error setting property 'forward' from form",
642: e1);
643: }
644: if (logger.isDebugEnabled()) {
645: logger.debug("setForward - end - return value = "
646: + null);
647: }
648: return null;
649: } catch (InvocationTargetException e) {
650: logger
651: .error(
652: "setForward - error setting property 'forward' from form",
653: e);
654: throw new SystemException(e);
655: } catch (IllegalAccessException e) {
656: logger
657: .error(
658: "setForward - error setting property 'forward' from form",
659: e);
660: throw new SystemException(e);
661: }
662:
663: if (logger.isDebugEnabled()) {
664: logger.debug("setForward() - end");
665: }
666: return forward;
667: }
668:
669: /**
670: * Get the user object for the user who is trying to login.
671: *
672: * @param request Current servlet request we are processing.
673: * @param form <em>Struts</em> form we are processing.
674: * @return User object for the user to be logged in.
675: * @throws SystemException If the user cannot be retrieved for any reason.
676: */
677: private UserDO initializeUser(final HttpServletRequest request,
678: final ActionForm form) throws SystemException {
679: assert (request != null);
680: assert (form != null);
681: HttpSession session = request.getSession();
682: SecuritySession securitySession = (SecuritySession) session
683: .getAttribute("securitySession");
684: assert (securitySession != null);
685: String userName = null;
686: UserDO user = null;
687: try {
688: userName = (String) PropertyUtils.getSimpleProperty(form,
689: "userName");
690: } catch (InvocationTargetException e) {
691: logger.error("execute - error getting userName property.",
692: e);
693: throw new SystemException(e);
694: } catch (IllegalAccessException e) {
695: logger.error(
696: "execute - error getting userName properties.", e);
697: throw new SystemException(e);
698: } catch (NoSuchMethodException e) {
699: logger.error(
700: "execute - error getting userName properties.", e);
701: throw new SystemException(e);
702: }
703: if (!StringHandling.isNullOrEmpty(userName)) {
704: try {
705: if (logger.isDebugEnabled()) {
706: logger.debug("Looking for entity for user name '"
707: + userName + "'");
708: }
709: user = security.findUserByName(securitySession,
710: userName);
711: } catch (FinderException e) {
712: logger.warn("No user found called '" + userName + "'",
713: e);
714: ActionErrors errors = new ActionErrors();
715: errors.add(ActionMessages.GLOBAL_MESSAGE,
716: new ActionMessage("login.error.login"));
717: saveErrors(request, (ActionMessages) errors);
718: saveToken(request);
719: }
720: }
721: // choose the theme
722: String siteTheme = request.getParameter("theme");
723: // go back to the last used?
724: if (StringHandling.isNullOrEmpty(siteTheme)
725: || USE_LAST_THEME.equals(siteTheme)) {
726: siteTheme = settings.getStringSetting(securitySession,
727: "siteTheme", user);
728: }
729: session.setAttribute(ThemeConstants.ATTRIBUTE_THEME_NAME,
730: siteTheme);
731: // if the user is null, create a default one so we have the name for
732: // debugging later
733: if (user == null) {
734: user = new UserDO();
735: user.setName(userName);
736: user.setId(null);
737: }
738: return user;
739: }
740:
741: /**
742: * Check to see if we are still using the default database. If so, we will
743: * forward to the site setup page.
744: *
745: * @param securitySession Used to lookup setting "siteDefaultDB".
746: * @return <code>true</code> if the site default database is being used and
747: * the user has not yet confirmed that this is OK.
748: * @throws SystemException If the PicoContainerFactory cannot be
749: * instantiated, or there is a problem accessing system setting
750: * "siteDefaultDB".
751: */
752: private boolean isDefaultDatabase(
753: final SecuritySession securitySession)
754: throws SystemException {
755: // if the URL is still set to the default database (in memory), check
756: // the user has confirmed this should be so and forward to the setup
757: // page, if not
758: PicoContainerFactory factory = PicoContainerFactory
759: .getInstance();
760: PicoContainer container = factory.getGlobalContainer();
761: assert (factory != null);
762: assert (container != null);
763: Properties hibernateProperties = (Properties) container
764: .getComponentInstance("hibernateProperties");
765: assert (hibernateProperties != null);
766: Boolean setupConfirmed = (Boolean) servlet
767: .getServletContext()
768: .getAttribute(HibernateSetupConstants.CONFIRM_ATTRIBUTE);
769: String uRL = hibernateProperties
770: .getProperty(HibernateSetupConstants.HIBERNATE_PROPERTY_DATABASE_URL);
771: assert (uRL != null);
772: String autoDB = HibernateSetupConstants.AUTOMATIC_DATABASE_MEMORY_URL
773: + settings.getStringSetting(securitySession,
774: "siteDefaultDB", null);
775: return autoDB.equals(uRL)
776: && !Boolean.TRUE.equals(setupConfirmed);
777: }
778:
779: /**
780: * This is the funky routine which actually logs the user into the site and
781: * handles any error.
782: *
783: * @param session Current HTTP session we are processing.
784: * @param form <em>Struts</em> form we are processing.
785: * @param user The user who should be logged in.
786: * @param errors Will append errors here if the user cannot log in.
787: * @return security session for the successfully logged in user, or a guest
788: * session if the user cannot log in (for security reasons).
789: * @throws SystemException If there is a technical reason preventing the
790: * user from logging in.
791: */
792: private SecuritySession login(final HttpSession session,
793: final ActionForm form, final UserDO user,
794: final ActionMessages errors) throws SystemException {
795: String password = null;
796: try {
797: password = (String) PropertyUtils.getSimpleProperty(form,
798: "password");
799: } catch (InvocationTargetException e) {
800: logger.error("execute - error getting password property.",
801: e);
802: throw new SystemException(e);
803: } catch (IllegalAccessException e) {
804: logger.error(
805: "execute - error getting password properties.", e);
806: throw new SystemException(e);
807: } catch (NoSuchMethodException e) {
808: logger.error(
809: "execute - error getting password properties.", e);
810: }
811: SecuritySession securitySession = null;
812: try {
813: if (logger.isInfoEnabled()) {
814: logger.info("Logging in user '" + user.getName()
815: + "' for real (not guest).");
816: }
817: securitySession = security.login(user, password);
818: session.setAttribute("securitySession", securitySession);
819: } catch (Exception e) {
820: // show the password only if the setting allows us to
821: String logPassword = "**********";
822: try {
823: securitySession = security.loginGuest();
824: Boolean debugPassword = settings
825: .getBooleanSetting(securitySession,
826: "siteLoginDebugPassword", null);
827: if ((debugPassword != null)
828: && debugPassword.booleanValue()) {
829: logPassword = password;
830: }
831: } catch (Exception e1) {
832: // nothing we can do - just log the error
833: logger
834: .error(
835: "Failed to access setting 'siteLoginDebugPassword'.",
836: e1);
837: }
838: logger.warn("Failed to login user '" + user.getName()
839: + "', password '" + logPassword + "'", e);
840: errors.add(ActionMessages.GLOBAL_MESSAGE,
841: new ActionMessage("login.error.login"));
842: }
843: return securitySession;
844: }
845: }
|