/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.struts.apps.mailreader.actions; import org.apache.commons.beanutils.PropertyUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; import org.apache.struts.action.DynaActionForm; import org.apache.struts.apps.mailreader.Constants; import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException; import org.apache.struts.apps.mailreader.dao.User; import org.apache.struts.apps.mailreader.dao.UserDatabase; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.lang.reflect.InvocationTargetException; /** * <p> * Provide an Edit method for retrieving an existing user, * and a Save method for updating or inserting a user. * </p><p> * Both methods utilize a RegistrationForm to obtain or expose User details. * If Save is used to create a user, * additional validations ensure input is nominal. * When a user is created, * Save also handles the initial logon. * </p> */ public final class RegistrationAction extends BaseAction { // --- Public Constants -- /** * <p> * Name of fromAddress field ["fromAddress"]. * </p> */ public final static String FROM_ADDRESS = "fromAddress"; /** * <p> * Name of fullName field ["fullName"]. * </p> */ public final static String FULL_NAME = "fullName"; /** * <p> * Name of password confirmation field ["password2"]. * </p> */ public final static String PASSWORD2 = "password2"; /** * <p> * Name of replyToAddress field ["replyToAddress"]. * </p> */ public final static String REPLY_TO_ADDRESS = "replyToAddress"; // ---- Private Methods ---- /** * <p> * The message prefix to use when populating a Registration Form. * </p> */ final String LOG_REGISTRATION_POPULATE = "RegistrationForm.populate"; /** * <p> * Helper method to post error message when user already exists. * </p> * * @param username Existing username * @param errors Our ActionMessages collection */ private void errorUsernameUnique(String username, ActionMessages errors) { errors.add( USERNAME, new org.apache.struts.action.ActionMessage( "error.username.unique", username)); } /** * <p> * Verify input for creating a new user, * create the user, and process the login. * </p> * * @param form The input form * @param request The HttpRequest being served * @param errors The ActionMessages collection for any errors * @return A new User and empty Errors if create succeeds, * or null and Errors if create fails */ private User doCreateUser( ActionForm form, HttpServletRequest request, ActionMessages errors) { if (log.isTraceEnabled()) { log.trace(" Perform additional validations on Create"); } UserDatabase database = doGetUserDatabase(); String username = doGet(form, USERNAME); try { if (database.findUser(username) != null) { errorUsernameUnique(username, errors); } } catch (ExpiredPasswordException e) { errorUsernameUnique(username, errors); errors.add("errors.literal", new ActionMessage(e.getMessage())); } String password = doGet(form, PASSWORD); if ((password == null) || (password.length() < 1)) { errors.add(PASSWORD, new ActionMessage("error.password.required")); String password2 = doGet(form, PASSWORD2); if ((password2 == null) || (password2.length() < 1)) { errors.add( PASSWORD2, new ActionMessage("error.password2.required")); } } if (!errors.isEmpty()) { return null; } User user = database.createUser(username); // Log the user in HttpSession session = request.getSession(); session.setAttribute(Constants.USER_KEY, user); if (log.isTraceEnabled()) { log.trace( " User: '" + user.getUsername() + "' logged on in session: " + session.getId()); } return user; } /** * <p> * Helper method to populate the input form from the User object. * </p> * * @param form Form with incoming values * @param user User object to populate * @throws ServletException On any error */ private void doPopulate(ActionForm form, User user) throws ServletException { final String title = Constants.EDIT; if (log.isTraceEnabled()) { log.trace(Constants.LOG_POPULATE_FORM + user); } try { PropertyUtils.copyProperties(form, user); DynaActionForm dyna = (DynaActionForm) form; dyna.set(TASK, title); dyna.set(PASSWORD, null); dyna.set(PASSWORD2, null); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t == null) { t = e; } log.error(LOG_REGISTRATION_POPULATE, t); throw new ServletException(LOG_REGISTRATION_POPULATE, t); } catch (Throwable t) { log.error(LOG_REGISTRATION_POPULATE, t); throw new ServletException(LOG_REGISTRATION_POPULATE, t); } } /** * <p> * Helper method to populate the User object from the input form. * </p> * * @param user User object to populate * @param form Form with incoming values * @throws ServletException On any error */ private void doPopulate(User user, ActionForm form) throws ServletException { if (log.isTraceEnabled()) { log.trace(Constants.LOG_POPULATE_USER + user); } try { String oldPassword = user.getPassword(); PropertyUtils.copyProperties(user, form); String password = doGet(form, PASSWORD); if ((password == null) || (password.length() < 1)) { user.setPassword(oldPassword); } } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t == null) { t = e; } log.error(LOG_REGISTRATION_POPULATE, t); throw new ServletException(LOG_REGISTRATION_POPULATE, t); } catch (Throwable t) { log.error(LOG_REGISTRATION_POPULATE, t); throw new ServletException(LOG_REGISTRATION_POPULATE, t); } } /** * <p> * Validate and clear the transactional token, * creating logging statements as needed. * </p> * * @param request Our HttpServletRequest * @param errors ActionErrors to transfer any messages */ private void doValidateToken(HttpServletRequest request, ActionMessages errors) { if (log.isTraceEnabled()) { log.trace(Constants.LOG_TOKEN_CHECK); } if (!isTokenValid(request)) { errors.add( ActionMessages.GLOBAL_MESSAGE, new ActionMessage(Constants.MSG_TRANSACTION_TOKEN)); } resetToken(request); } // ----- Public Methods ---- /** * <p> * Retrieve the User object to edit or null if the User does not exist, * and set an transactional token to later detect multiple Save commands. * </p> * * @param mapping Our ActionMapping * @param form Our ActionForm * @param request Our HttpServletRequest * @param response Our HttpServletResponse * @return The "Success" result for this mapping * @throws Exception on any error */ public ActionForward Edit( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { final String method = Constants.EDIT; doLogProcess(mapping, method); HttpSession session = request.getSession(); User user = doGetUser(session); boolean updating = (user != null); if (updating) { doPopulate(form, user); } doSaveToken(request); return doFindSuccess(mapping); } /** * <p> * Insert or update a User object to the persistent store. * </p><p> * If a User is not logged in, * then a new User is created and automatically logged in. * Otherwise, the existing User is updated. * </p> * * @param mapping Our ActionMapping * @param form Our ActionForm * @param request Our HttpServletRequest * @param response Our HttpServletResponse * @return The "Success" result for this mapping * @throws Exception on any error */ public ActionForward Save( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { final String method = Constants.SAVE; doLogProcess(mapping, method); HttpSession session = request.getSession(); if (isCancelled(request)) { doCancel(session, method, Constants.SUBSCRIPTION_KEY); return doFindSuccess(mapping); } ActionMessages errors = new ActionMessages(); doValidateToken(request, errors); if (!errors.isEmpty()) { return doInputForward(mapping, request, errors); } User user = doGetUser(session); if (user == null) { user = doCreateUser(form, request, errors); if (!errors.isEmpty()) { return doInputForward(mapping, request, errors); } } doPopulate(user, form); doSaveUser(user); return doFindSuccess(mapping); } }