package org.appfuse.webapp.controller; import java.util.Locale; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.appfuse.Constants; import org.appfuse.model.Role; import org.appfuse.model.User; import org.appfuse.service.RoleManager; import org.appfuse.service.UserExistsException; import org.appfuse.service.UserManager; import org.appfuse.webapp.util.RequestUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mail.MailException; import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.ServletRequestDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; /** * Implementation of <strong>SimpleFormController</strong> that interacts with * the {@link UserManager} to retrieve/persist values to the database. * * <p><a href="UserFormController.java.html"><i>View Source</i></a> * * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a> */ @Controller @RequestMapping("/userform*") public class UserFormController extends BaseFormController { private RoleManager roleManager; @Autowired public void setRoleManager(final RoleManager roleManager) { this.roleManager = roleManager; } public UserFormController() { setCancelView("redirect:/home"); setSuccessView("redirect:/admin/users"); } @Override @InitBinder protected void initBinder(final HttpServletRequest request, final ServletRequestDataBinder binder) { super.initBinder(request, binder); binder.setDisallowedFields("password", "confirmPassword"); } /** * Load user object from db before web data binding in order to keep properties not populated from web post. * * @param request * @return */ @ModelAttribute("user") protected User loadUser(final HttpServletRequest request) { final String userId = request.getParameter("id"); if (isFormSubmission(request) && StringUtils.isNotBlank(userId)) { return getUserManager().getUser(userId); } return new User(); } @RequestMapping(method = RequestMethod.POST) public String onSubmit(@ModelAttribute("user") final User user, final BindingResult errors, final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (request.getParameter("cancel") != null) { if (!StringUtils.equals(request.getParameter("from"), "list")) { return getCancelView(); } else { return getSuccessView(); } } if (validator != null) { // validator is null during testing validator.validate(user, errors); if (errors.hasErrors() && request.getParameter("delete") == null) { // don't validate when deleting return "userform"; } } log.debug("entering 'onSubmit' method..."); final Locale locale = request.getLocale(); if (request.getParameter("delete") != null) { getUserManager().removeUser(user.getId().toString()); saveMessage(request, getText("user.deleted", user.getFullName(), locale)); return getSuccessView(); } else { // only attempt to change roles if user is admin for other users, // showForm() method will handle populating if (request.isUserInRole(Constants.ADMIN_ROLE)) { final String[] userRoles = request.getParameterValues("userRoles"); if (userRoles != null) { user.getRoles().clear(); for (final String roleName : userRoles) { user.addRole(roleManager.getRole(roleName)); } } } else { // if user is not an admin then load roles from the database // (or any other user properties that should not be editable // by users without admin role) final User cleanUser = getUserManager().getUserByUsername( request.getRemoteUser()); user.setRoles(cleanUser.getRoles()); } final Integer originalVersion = user.getVersion(); // set a random password if user is added by admin if (originalVersion == null && StringUtils.isBlank(user.getPassword())) { user.setPassword(UUID.randomUUID().toString()); // XXX review if // UUID is a // good choice // here } try { getUserManager().saveUser(user); } catch (final AccessDeniedException ade) { // thrown by UserSecurityAdvice configured in aop:advisor userManagerSecurity log.warn(ade.getMessage()); response.sendError(HttpServletResponse.SC_FORBIDDEN); return null; } catch (final UserExistsException e) { errors.rejectValue("username", "errors.existing.user", new Object[] { user.getUsername(), user.getEmail() }, "duplicate user"); // reset the version # to what was passed in user.setVersion(originalVersion); return "userform"; } if (!StringUtils.equals(request.getParameter("from"), "list")) { saveMessage(request, getText("user.saved", user.getFullName(), locale)); // return to main Menu return getCancelView(); } else { if (StringUtils.isBlank(request.getParameter("version"))) { saveMessage(request, getText("user.added", user.getFullName(), locale)); // Send an account information e-mail message.setSubject(getText("signup.email.subject", locale)); try { final String resetPasswordUrl = getUserManager().buildRecoveryPasswordUrl(user, UpdatePasswordController.RECOVERY_PASSWORD_TEMPLATE); sendUserMessage(user, getText("newuser.email.message", user.getFullName(), locale), RequestUtil.getAppURL(request) + resetPasswordUrl); } catch (final MailException me) { saveError(request, me.getCause().getLocalizedMessage()); } return getSuccessView(); } else { saveMessage(request, getText("user.updated.byAdmin", user.getFullName(), locale)); } } } return "userform"; } @ModelAttribute @RequestMapping(method = RequestMethod.GET) protected User showForm(final HttpServletRequest request, final HttpServletResponse response) throws Exception { // If not an administrator, make sure user is not trying to add or edit another user if (!request.isUserInRole(Constants.ADMIN_ROLE) && !isFormSubmission(request)) { if (isAdd(request) || request.getParameter("id") != null) { response.sendError(HttpServletResponse.SC_FORBIDDEN); log.warn("User '" + request.getRemoteUser() + "' is trying to edit user with id '" + request.getParameter("id") + "'"); throw new AccessDeniedException("You do not have permission to modify other users."); } } if (!isFormSubmission(request)) { final String userId = request.getParameter("id"); User user; if (userId == null && !isAdd(request)) { user = getUserManager().getUserByUsername(request.getRemoteUser()); } else if (!StringUtils.isBlank(userId) && !"".equals(request.getParameter("version"))) { user = getUserManager().getUser(userId); } else { user = new User(); user.addRole(new Role(Constants.USER_ROLE)); } return user; } else { // populate user object from database, so all fields don't need to be hidden fields in form return getUserManager().getUser(request.getParameter("id")); } } private boolean isFormSubmission(final HttpServletRequest request) { return request.getMethod().equalsIgnoreCase("post"); } protected boolean isAdd(final HttpServletRequest request) { final String method = request.getParameter("method"); return (method != null && method.equalsIgnoreCase("add")); } }