View Javadoc
1   /*******************************************************************************
2    *   Gisgraphy Project 
3    * 
4    *   This library is free software; you can redistribute it and/or
5    *   modify it under the terms of the GNU Lesser General Public
6    *   License as published by the Free Software Foundation; either
7    *   version 2.1 of the License, or (at your option) any later version.
8    * 
9    *   This library is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   *   Lesser General Public License for more details.
13   * 
14   *   You should have received a copy of the GNU Lesser General Public
15   *   License along with this library; if not, write to the Free Software
16   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
17   * 
18   *  Copyright 2008  Gisgraphy project 
19   *  David Masclet <davidmasclet@gisgraphy.com>
20   *  
21   *  
22   *******************************************************************************/
23  package com.gisgraphy.webapp.action;
24  
25  import java.io.IOException;
26  import java.util.ArrayList;
27  import java.util.List;
28  
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  
32  import org.springframework.security.AccessDeniedException;
33  import org.springframework.security.Authentication;
34  import org.springframework.security.AuthenticationTrustResolver;
35  import org.springframework.security.AuthenticationTrustResolverImpl;
36  import org.springframework.security.context.SecurityContext;
37  import org.springframework.security.context.SecurityContextHolder;
38  import org.apache.struts2.ServletActionContext;
39  
40  import com.gisgraphy.Constants;
41  import com.gisgraphy.model.Role;
42  import com.gisgraphy.model.User;
43  import com.gisgraphy.service.UserExistsException;
44  import com.gisgraphy.util.StringUtil;
45  import com.gisgraphy.webapp.util.RequestUtil;
46  import com.opensymphony.xwork2.Preparable;
47  
48  /**
49   * Action for facilitating User Management feature.
50   */
51  public class UserAction extends BaseAction implements Preparable {
52      private static final long serialVersionUID = 6776558938712115191L;
53  
54      private List<User> users;
55  
56      private User user;
57  
58      private String id;
59  
60      /**
61       * Grab the entity from the database before populating with request
62       * parameters
63       */
64      public void prepare() {
65  	if (getRequest().getMethod().equalsIgnoreCase("post")) {
66  	    // prevent failures on new
67  	    if (!"".equals(getRequest().getParameter("user.id"))) {
68  		user = userManager
69  			.getUser(getRequest().getParameter("user.id"));
70  	    }
71  	}
72      }
73  
74      /**
75       * Holder for users to display on list screen
76       * 
77       * @return list of users
78       */
79      public List<User> getUsers() {
80  	return users;
81      }
82  
83      public void setId(String id) {
84  	this.id = id;
85      }
86  
87      public User getUser() {
88  	return user;
89      }
90  
91      public void setUser(User user) {
92  	this.user = user;
93      }
94  
95      /**
96       * Delete the user passed in.
97       * 
98       * @return success
99       */
100     public String delete() {
101 	userManager.removeUser(user.getId().toString());
102 	List<String> args = new ArrayList<String>();
103 	args.add(user.getFullName());
104 	saveMessage(getText("user.deleted", args.toArray(new String[]{})));
105 
106 	return SUCCESS;
107     }
108 
109     /**
110      * Grab the user from the database based on the "id" passed in.
111      * 
112      * @return success if user found
113      * @throws IOException
114      *                 can happen when sending a "forbidden" from
115      *                 response.sendError()
116      */
117     public String edit() throws IOException {
118 	HttpServletRequest request = getRequest();
119 	boolean editProfile = (request.getRequestURI().indexOf("editProfile") > -1);
120 
121 	// if URL is "editProfile" - make sure it's the current user
122 	if (editProfile) {
123 	    // reject if id passed in or "list" parameter passed in
124 	    // someone that is trying this probably knows the AppFuse code
125 	    // but it's a legitimate bug, so I'll fix it. ;-)
126 	    if ((request.getParameter("id") != null)
127 		    || (request.getParameter("from") != null)) {
128 		ServletActionContext.getResponse().sendError(
129 			HttpServletResponse.SC_FORBIDDEN);
130 		log.warn("User '" + request.getRemoteUser()
131 			+ "' is trying to edit user '"
132 			+ request.getParameter("id") + "'");
133 
134 		return null;
135 	    }
136 	}
137 
138 	// if a user's id is passed in
139 	if (id != null) {
140 	    // lookup the user using that id
141 	    user = userManager.getUser(id);
142 	} else if (editProfile) {
143 	    user = userManager.getUserByUsername(request.getRemoteUser());
144 	} else {
145 	    user = new User();
146 	    user.addRole(new Role(Constants.USER_ROLE));
147 	}
148 
149 	if (user.getUsername() != null) {
150 	    user.setConfirmPassword(user.getPassword());
151 
152 	    // if user logged in with remember me, display a warning that they
153 	    // can't change passwords
154 	    log.debug("checking for remember me login...");
155 
156 	    AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl();
157 	    SecurityContext ctx = SecurityContextHolder.getContext();
158 
159 	    if (ctx != null) {
160 		Authentication auth = ctx.getAuthentication();
161 
162 		if (resolver.isRememberMe(auth)) {
163 		    getSession().setAttribute("cookieLogin", "true");
164 		    saveMessage(getText("userProfile.cookieLogin"));
165 		}
166 	    }
167 	}
168 
169 	return SUCCESS;
170     }
171 
172     /**
173      * Default: just returns "success"
174      * 
175      * @return "success"
176      */
177     @Override
178     public String execute() {
179 	return SUCCESS;
180     }
181 
182     /**
183      * Sends users to "mainMenu" when !from.equals("list"). Sends everyone else
184      * to "cancel"
185      * 
186      * @return "mainMenu" or "cancel"
187      */
188     @Override
189     public String cancel() {
190 	if (!"list".equals(from)) {
191 	    return "mainMenu";
192 	}
193 	return "cancel";
194     }
195 
196     /**
197      * Save user
198      * 
199      * @return success if everything worked, otherwise input
200      * @throws IOException
201      *                 when setting "access denied" fails on response
202      */
203     public String save() throws IOException {
204 	Boolean encrypt = (Boolean) getConfiguration().get(
205 		Constants.ENCRYPT_PASSWORD);
206 
207 	if ("true".equals(getRequest().getParameter("encryptPass"))
208 		&& (encrypt != null && encrypt)) {
209 	    String algorithm = (String) getConfiguration().get(
210 		    Constants.ENC_ALGORITHM);
211 
212 	    if (algorithm == null) { // should only happen for test case
213 		log.debug("assuming testcase, setting algorithm to 'SHA'");
214 		algorithm = "SHA";
215 	    }
216 
217 	    user.setPassword(StringUtil.encodePassword(user.getPassword(),
218 		    algorithm));
219 	}
220 
221 	Integer originalVersion = user.getVersion();
222 
223 	boolean isNew = ("".equals(getRequest().getParameter("user.version")));
224 	// only attempt to change roles if user is admin
225 	// for other users, prepare() method will handle populating
226 	if (getRequest().isUserInRole(Constants.ADMIN_ROLE)) {
227 	    user.getRoles().clear(); // APF-788: Removing roles from user
228 	    // doesn't work
229 	    String[] userRoles = getRequest().getParameterValues("userRoles");
230 
231 	    for (int i = 0; userRoles != null && i < userRoles.length; i++) {
232 		String roleName = userRoles[i];
233 		user.addRole(roleManager.getRole(roleName));
234 	    }
235 	}
236 
237 	try {
238 	    user = userManager.saveUser(user);
239 	} catch (AccessDeniedException ade) {
240 	    // thrown by UserSecurityAdvice configured in aop:advisor
241 	    // userManagerSecurity
242 	    log.warn(ade.getMessage());
243 	    getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
244 	    return null;
245 	} catch (UserExistsException e) {
246 	    List<String> args = new ArrayList<String>();
247 	    args.add(user.getUsername());
248 	    args.add(user.getEmail());
249 	    addActionError(getText("errors.existing.user", args.toArray(new String[]{})));
250 
251 	    // reset the version # to what was passed in
252 	    user.setVersion(originalVersion);
253 	    // redisplay the unencrypted passwords
254 	    user.setPassword(user.getConfirmPassword());
255 	    return INPUT;
256 	}
257 
258 	if (!"list".equals(from)) {
259 	    // add success messages
260 	    saveMessage(getText("user.saved"));
261 	    return "mainMenu";
262 	} else {
263 	    // add success messages
264 	    List<String> args = new ArrayList<String>();
265 	    args.add(user.getFullName());
266 	    if (isNew) {
267 		saveMessage(getText("user.added", args.toArray(new String[]{})));
268 		// Send an account information e-mail
269 		mailMessage.setSubject(getText("signup.email.subject"));
270 		sendUserMessage(user, getText("newuser.email.message", args.toArray(new String[]{})),
271 			RequestUtil.getAppURL(getRequest()));
272 		return SUCCESS;
273 	    } else {
274 		saveMessage(getText("user.updated.byAdmin", args.toArray(new String[]{})));
275 		return INPUT;
276 	    }
277 	}
278     }
279 
280     /**
281      * Fetch all users from database and put into local "users" variable for
282      * retrieval in the UI.
283      * 
284      * @return "success" if no exceptions thrown
285      */
286     public String list() {
287 	users = userManager.getUsers(new User());
288 	return SUCCESS;
289     }
290 }