View Javadoc

1   package org.appfuse.webapp.server.services.impl;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.List;
6   import java.util.Locale;
7   import java.util.Set;
8   
9   import javax.servlet.http.Cookie;
10  import javax.servlet.http.HttpServletRequest;
11  import javax.servlet.http.HttpServletResponse;
12  
13  import org.apache.commons.lang.RandomStringUtils;
14  import org.apache.commons.lang.StringUtils;
15  import org.apache.commons.lang.math.RandomUtils;
16  import org.appfuse.Constants;
17  import org.appfuse.model.Role;
18  import org.appfuse.model.User;
19  import org.appfuse.service.RoleManager;
20  import org.appfuse.service.UserExistsException;
21  import org.appfuse.service.UserManager;
22  import org.appfuse.webapp.client.proxies.RoleProxy;
23  import org.appfuse.webapp.listener.UserCounterListener;
24  import org.appfuse.webapp.server.services.UserRequestService;
25  import org.appfuse.webapp.server.services.UsersSearchCriteria;
26  import org.appfuse.webapp.util.RequestUtil;
27  import org.springframework.beans.factory.annotation.Autowired;
28  import org.springframework.beans.support.PropertyComparator;
29  import org.springframework.context.i18n.LocaleContextHolder;
30  import org.springframework.mail.MailException;
31  import org.springframework.security.access.AccessDeniedException;
32  import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
33  import org.springframework.security.core.context.SecurityContextHolder;
34  import org.springframework.security.core.userdetails.UsernameNotFoundException;
35  import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
36  import org.springframework.stereotype.Component;
37  
38  @Component("userRequestService")
39  public class UserRequestServiceImpl extends AbstractBaseRequest implements UserRequestService {
40  
41      public static final String RECOVERY_PASSWORD_TEMPLATE = "/#updatePassword:username={username}!token={token}";
42  
43      @Autowired
44      private UserManager userManager;
45      @Autowired
46      private RoleManager roleManager;
47  
48      /**
49       * 
50       * @return
51       */
52      @Override
53      public User getCurrentUser() {
54          final String username = getCurrentUsername();
55          if (username != null) {
56              final User user = userManager.getUserByUsername(username);
57              if (isFullyAuthenticated()) {
58                  user.getRoles().add(new Role(RoleProxy.FULLY_AUTHENTICATED));
59              }
60              return user;
61          }
62          return null;
63      }
64  
65      /**
66       * 
67       * @return
68       */
69      @Override
70      public User signUp() {
71          return new User();
72      }
73  
74      /**
75       * 
76       * @param user
77       * @return
78       * @throws Exception
79       */
80      @Override
81      public User signUp(final User user) throws Exception {
82          user.setEnabled(true);
83          // Set the default user role on this new user
84          user.getRoles().clear();
85          user.addRole(roleManager.getRole(Constants.USER_ROLE));
86  
87          try {
88              userManager.saveUser(user);
89          } catch (final UserExistsException e) {
90              log.debug(String.format("Trying to duplicate user username=%s, email=%d", user.getUsername(), user.getEmail()), e);
91              // errors.rejectValue("username", "errors.existing.user",
92              // new Object[]{user.getUsername(), user.getEmail()},
93              // "duplicate user");
94              throw e;
95          }
96  
97          // log user in automatically
98          final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
99                  user.getUsername(), user.getConfirmPassword(), user.getAuthorities());
100         auth.setDetails(user);
101         SecurityContextHolder.getContext().setAuthentication(auth);
102 
103         // Send user an e-mail
104         if (log.isDebugEnabled()) {
105             log.debug("Sending user '" + user.getUsername() + "' an account information e-mail");
106         }
107 
108         // Send an account information e-mail
109         final Locale locale = LocaleContextHolder.getLocale();
110         message.setSubject(getText("signup.email.subject", locale));
111 
112         try {
113             sendUserMessage(user, "accountCreated.vm", getText("signup.email.message", locale), RequestUtil.getAppURL(getServletRequest()));
114         } catch (final MailException me) {
115             // saveError(request, me.getMostSpecificCause().getMessage());
116             throw me;
117         }
118 
119         return user;
120     }
121 
122     /**
123      * 
124      * @return
125      */
126     @Override
127     public User editProfile() {
128         final String username = getCurrentUsername();
129         final User user = userManager.getUserByUsername(username);
130         user.setConfirmPassword(user.getPassword());
131         return user;
132     }
133 
134     /**
135      * 
136      * @param user
137      * @return
138      * @throws Exception
139      */
140     @Override
141     public User editProfile(final User user) throws Exception {
142         final String username = getCurrentUsername();
143         if (!username.equals(user.getUsername())) {
144             throw new AccessDeniedException("Trying to edit another users profile");
145         }
146         return userManager.saveUser(user);
147     }
148 
149     /**
150      * 
151      * @param userId
152      * @return
153      */
154     @Override
155     public User getUser(final Long userId) {
156         final User user = userManager.get(userId);
157         user.setConfirmPassword(user.getPassword());
158         return user;
159     }
160 
161     /**
162      * 
163      * @param user
164      * @return
165      * @throws Exception
166      */
167     @Override
168     public User saveUser(final User user) throws Exception {
169         if (user.getVersion() == null && user.getPassword() == null) {
170             final int length = RandomUtils.nextInt(8) + 8;
171             user.setPassword(RandomStringUtils.randomAlphanumeric(length));
172         }
173         return userManager.saveUser(user);
174     }
175 
176     /**
177      * 
178      * @param searchCriteria
179      * @return
180      */
181     @Override
182     public long countUsers(final UsersSearchCriteria searchCriteria) {
183         final String searchTerm = searchCriteria != null ? searchCriteria.getSearchTerm() : null;
184         return userManager.search(searchTerm).size();
185     }
186 
187     /**
188      * 
189      * @param searchCriteria
190      * @param firstResult
191      * @param maxResults
192      * @return
193      */
194     @Override
195     public List<User> searchUsers(final UsersSearchCriteria searchCriteria, final int firstResult, final int maxResults) {
196         return searchUsers(searchCriteria, firstResult, maxResults, null, true);
197     }
198 
199     /**
200      * 
201      * @param searchCriteria
202      * @param firstResult
203      * @param maxResults
204      * @return
205      */
206     @Override
207     public List<User> searchUsers(final UsersSearchCriteria searchCriteria, final int firstResult, final int maxResults, final String sortProperty, final boolean ascending) {
208         final String searchTerm = searchCriteria != null ? searchCriteria.getSearchTerm() : null;
209         final List<User> users = userManager.search(searchTerm);
210         if (StringUtils.isNotEmpty(sortProperty)) {
211             log.debug(String.format("Sorting usersList by property='%s', ascending='%s'", sortProperty, ascending));
212             Collections.sort(users, new PropertyComparator(sortProperty, true, ascending));
213         }
214         final int fromIndex = Math.min(firstResult, users.size());
215         final int toIndex = Math.min(fromIndex + maxResults, users.size());
216         log.debug(String.format("searchUsers(%d,%d) %d-%d [%d]", firstResult, maxResults, fromIndex, toIndex, users.size()));
217         return users.subList(fromIndex, toIndex);
218     }
219 
220     /**
221      * 
222      * @param user
223      */
224     @Override
225     public void removeUser(final Long userId) {
226         userManager.removeUser(userId.toString());
227     }
228 
229     /**
230      * 
231      * @param username
232      * @return
233      */
234     @Override
235     public String sendPasswordHint(final String username) {
236         final Locale locale = LocaleContextHolder.getLocale();
237 
238         // ensure that the username has been sent
239         if (username == null) {
240             log.warn("Username not specified, notifying user that it's a required field.");
241             return null;
242         }
243 
244         log.debug("Processing Password Hint...");
245 
246         // look up the user's information
247         try {
248             final User user = userManager.getUserByUsername(username);
249 
250             final StringBuffer msg = new StringBuffer();
251             msg.append("Your password hint is: ").append(user.getPasswordHint());
252             msg.append("\n\nLogin at: ").append(RequestUtil.getAppURL(getServletRequest()));
253 
254             message.setTo(user.getEmail());
255             final String subject =
256                     '[' + getText("webapp.name", locale) + "] " +
257                             getText("user.passwordHint", locale);
258             message.setSubject(subject);
259             message.setText(msg.toString());
260             mailEngine.send(message);
261             return user.getFullName();// XXX disabling returning
262                                       // user.getEmail();
263         } catch (final UsernameNotFoundException e) {
264             log.warn(e.getMessage());
265         } catch (final MailException me) {
266             log.warn(me.getMessage());
267         }
268         return null;
269     }
270 
271     /**
272      * 
273      * @param username
274      * @return
275      */
276     @Override
277     public String requestRecoveryToken(final String username) {
278         final Locale locale = LocaleContextHolder.getLocale();
279 
280         log.debug("Sending recovery token to user " + username);
281         try {
282             userManager.sendPasswordRecoveryEmail(username, RequestUtil.getAppURL(getServletRequest()) + RECOVERY_PASSWORD_TEMPLATE);
283         } catch (final UsernameNotFoundException ignored) {
284             // lets ignore this
285         }
286         return getText("updatePassword.recoveryToken.sent", locale);
287     }
288 
289     /**
290      * 
291      * @param username
292      * @param token
293      * @param currentPassword
294      * @param password
295      * @return
296      * @throws UserExistsException
297      */
298     @Override
299     public User updatePassword(
300             final String username,
301             final String token,
302             final String currentPassword,
303             final String password)
304             throws UserExistsException {
305 
306         final HttpServletRequest request = getServletRequest();
307 
308         if (StringUtils.isEmpty(password)) {
309             return null;
310         }
311 
312         User user = null;
313         final boolean usingToken = StringUtils.isNotBlank(token);
314         if (usingToken) {
315             log.debug("Updating Password for username " + username + ", using reset token");
316             user = userManager.updatePassword(username, null, token, password, RequestUtil.getAppURL(request));
317 
318         } else {
319             log.debug("Updating Password for username " + username + ", using current password");
320             if (!username.equals(getCurrentUser().getUsername())) {
321                 throw new AccessDeniedException("You do not have permission to modify other users password.");
322             }
323             user = userManager.updatePassword(username, currentPassword, null, password,
324                     RequestUtil.getAppURL(request));
325         }
326 
327         return user;
328     }
329 
330     /**
331      * 
332      * @return
333      */
334     @Override
335     public List<User> getActiveUsers() {
336         return new ArrayList((Set) getServletContext().getAttribute(UserCounterListener.USERS_KEY));
337     }
338 
339     /**
340      * 
341      */
342     @Override
343     public boolean logout() {
344         final HttpServletRequest request = getServletRequest();
345         final HttpServletResponse response = getServletResponse();
346         if (request.getSession(false) != null) {
347             request.getSession(false).invalidate();
348         }
349         final Cookie terminate = new Cookie(TokenBasedRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, null);
350         final String contextPath = request.getContextPath();
351         terminate.setPath(contextPath != null && contextPath.length() > 0 ? contextPath : "/");
352         terminate.setMaxAge(0);
353         response.addCookie(terminate);
354         return true;
355     }
356 }