View Javadoc

1   package org.appfuse.webapp.controller;
2   
3   import java.util.Locale;
4   import java.util.UUID;
5   
6   import javax.servlet.http.HttpServletRequest;
7   import javax.servlet.http.HttpServletResponse;
8   
9   import org.apache.commons.lang.StringUtils;
10  import org.appfuse.Constants;
11  import org.appfuse.model.Role;
12  import org.appfuse.model.User;
13  import org.appfuse.service.RoleManager;
14  import org.appfuse.service.UserExistsException;
15  import org.appfuse.service.UserManager;
16  import org.appfuse.webapp.util.RequestUtil;
17  import org.springframework.beans.factory.annotation.Autowired;
18  import org.springframework.mail.MailException;
19  import org.springframework.security.access.AccessDeniedException;
20  import org.springframework.stereotype.Controller;
21  import org.springframework.validation.BindingResult;
22  import org.springframework.web.bind.ServletRequestDataBinder;
23  import org.springframework.web.bind.annotation.InitBinder;
24  import org.springframework.web.bind.annotation.ModelAttribute;
25  import org.springframework.web.bind.annotation.RequestMapping;
26  import org.springframework.web.bind.annotation.RequestMethod;
27  
28  /**
29   * Implementation of <strong>SimpleFormController</strong> that interacts with
30   * the {@link UserManager} to retrieve/persist values to the database.
31   *
32   * <p><a href="UserFormController.java.html"><i>View Source</i></a>
33   *
34   * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
35   */
36  @Controller
37  @RequestMapping("/userform*")
38  public class UserFormController extends BaseFormController {
39  
40      private RoleManager roleManager;
41  
42      @Autowired
43      public void setRoleManager(final RoleManager roleManager) {
44          this.roleManager = roleManager;
45      }
46  
47      public UserFormController() {
48          setCancelView("redirect:/home");
49          setSuccessView("redirect:/admin/users");
50      }
51  
52      @Override
53      @InitBinder
54      protected void initBinder(final HttpServletRequest request, final ServletRequestDataBinder binder) {
55          super.initBinder(request, binder);
56          binder.setDisallowedFields("password", "confirmPassword");
57      }
58  
59      /**
60       * Load user object from db before web data binding in order to keep properties not populated from web post.
61       * 
62       * @param request
63       * @return
64       */
65      @ModelAttribute("user")
66      protected User loadUser(final HttpServletRequest request) {
67          final String userId = request.getParameter("id");
68          if (isFormSubmission(request) && StringUtils.isNotBlank(userId)) {
69              return getUserManager().getUser(userId);
70          }
71          return new User();
72      }
73  
74      @RequestMapping(method = RequestMethod.POST)
75      public String onSubmit(@ModelAttribute("user") final User user, final BindingResult errors, final HttpServletRequest request,
76              final HttpServletResponse response)
77              throws Exception {
78          if (request.getParameter("cancel") != null) {
79              if (!StringUtils.equals(request.getParameter("from"), "list")) {
80                  return getCancelView();
81              } else {
82                  return getSuccessView();
83              }
84          }
85  
86          if (validator != null) { // validator is null during testing
87              validator.validate(user, errors);
88  
89              if (errors.hasErrors() && request.getParameter("delete") == null) { // don't validate when deleting
90                  return "userform";
91              }
92          }
93  
94          log.debug("entering 'onSubmit' method...");
95  
96          final Locale locale = request.getLocale();
97  
98          if (request.getParameter("delete") != null) {
99              getUserManager().removeUser(user.getId().toString());
100             saveMessage(request, getText("user.deleted", user.getFullName(), locale));
101 
102             return getSuccessView();
103         } else {
104 
105             // only attempt to change roles if user is admin for other users,
106             // showForm() method will handle populating
107             if (request.isUserInRole(Constants.ADMIN_ROLE)) {
108                 final String[] userRoles = request.getParameterValues("userRoles");
109 
110                 if (userRoles != null) {
111                     user.getRoles().clear();
112                     for (final String roleName : userRoles) {
113                         user.addRole(roleManager.getRole(roleName));
114                     }
115                 }
116             } else {
117                 // if user is not an admin then load roles from the database
118                 // (or any other user properties that should not be editable
119                 // by users without admin role)
120                 final User cleanUser = getUserManager().getUserByUsername(
121                         request.getRemoteUser());
122                 user.setRoles(cleanUser.getRoles());
123             }
124 
125             final Integer originalVersion = user.getVersion();
126 
127             // set a random password if user is added by admin
128             if (originalVersion == null && StringUtils.isBlank(user.getPassword())) {
129                 user.setPassword(UUID.randomUUID().toString()); // XXX review if
130                 // UUID is a
131                 // good choice
132                 // here
133             }
134 
135             try {
136                 getUserManager().saveUser(user);
137             } catch (final AccessDeniedException ade) {
138                 // thrown by UserSecurityAdvice configured in aop:advisor userManagerSecurity
139                 log.warn(ade.getMessage());
140                 response.sendError(HttpServletResponse.SC_FORBIDDEN);
141                 return null;
142             } catch (final UserExistsException e) {
143                 errors.rejectValue("username", "errors.existing.user",
144                         new Object[] { user.getUsername(), user.getEmail() }, "duplicate user");
145 
146                 // reset the version # to what was passed in
147                 user.setVersion(originalVersion);
148 
149                 return "userform";
150             }
151 
152             if (!StringUtils.equals(request.getParameter("from"), "list")) {
153                 saveMessage(request, getText("user.saved", user.getFullName(), locale));
154 
155                 // return to main Menu
156                 return getCancelView();
157             } else {
158                 if (StringUtils.isBlank(request.getParameter("version"))) {
159                     saveMessage(request, getText("user.added", user.getFullName(), locale));
160 
161                     // Send an account information e-mail
162                     message.setSubject(getText("signup.email.subject", locale));
163 
164                     try {
165                         final String resetPasswordUrl = getUserManager().buildRecoveryPasswordUrl(user,
166                                 UpdatePasswordController.RECOVERY_PASSWORD_TEMPLATE);
167                         sendUserMessage(user, getText("newuser.email.message", user.getFullName(), locale),
168                                 RequestUtil.getAppURL(request) + resetPasswordUrl);
169                     } catch (final MailException me) {
170                         saveError(request, me.getCause().getLocalizedMessage());
171                     }
172 
173                     return getSuccessView();
174                 } else {
175                     saveMessage(request, getText("user.updated.byAdmin", user.getFullName(), locale));
176                 }
177             }
178         }
179 
180         return "userform";
181     }
182 
183     @ModelAttribute
184     @RequestMapping(method = RequestMethod.GET)
185     protected User showForm(final HttpServletRequest request, final HttpServletResponse response)
186             throws Exception {
187         // If not an administrator, make sure user is not trying to add or edit another user
188         if (!request.isUserInRole(Constants.ADMIN_ROLE) && !isFormSubmission(request)) {
189             if (isAdd(request) || request.getParameter("id") != null) {
190                 response.sendError(HttpServletResponse.SC_FORBIDDEN);
191                 log.warn("User '" + request.getRemoteUser() + "' is trying to edit user with id '" +
192                         request.getParameter("id") + "'");
193 
194                 throw new AccessDeniedException("You do not have permission to modify other users.");
195             }
196         }
197 
198         if (!isFormSubmission(request)) {
199             final String userId = request.getParameter("id");
200 
201             User user;
202             if (userId == null && !isAdd(request)) {
203                 user = getUserManager().getUserByUsername(request.getRemoteUser());
204             } else if (!StringUtils.isBlank(userId) && !"".equals(request.getParameter("version"))) {
205                 user = getUserManager().getUser(userId);
206             } else {
207                 user = new User();
208                 user.addRole(new Role(Constants.USER_ROLE));
209             }
210 
211             return user;
212         } else {
213             // populate user object from database, so all fields don't need to be hidden fields in form
214             return getUserManager().getUser(request.getParameter("id"));
215         }
216     }
217 
218     private boolean isFormSubmission(final HttpServletRequest request) {
219         return request.getMethod().equalsIgnoreCase("post");
220     }
221 
222     protected boolean isAdd(final HttpServletRequest request) {
223         final String method = request.getParameter("method");
224         return (method != null && method.equalsIgnoreCase("add"));
225     }
226 }