View Javadoc

1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  package org.itracker.web.actions.base;
19  
20  import java.io.IOException;
21  import java.net.MalformedURLException;
22  import java.net.URL;
23  import java.util.Date;
24  import java.util.Locale;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import javax.servlet.ServletException;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  import javax.servlet.http.HttpSession;
32  
33  import org.apache.log4j.Level;
34  import org.apache.log4j.Logger;
35  import org.apache.struts.Globals;
36  import org.apache.struts.action.Action;
37  import org.apache.struts.action.ActionErrors;
38  import org.apache.struts.action.ActionForm;
39  import org.apache.struts.action.ActionForward;
40  import org.apache.struts.action.ActionMapping;
41  import org.apache.struts.action.ActionMessage;
42  import org.apache.struts.action.ActionMessages;
43  import org.itracker.model.PermissionType;
44  import org.itracker.model.User;
45  import org.itracker.services.ConfigurationService;
46  import org.itracker.services.ITrackerServices;
47  import org.itracker.services.util.UserUtilities;
48  import org.itracker.web.util.Constants;
49  import org.itracker.web.util.LoginUtilities;
50  import org.itracker.web.util.RequestHelper;
51  import org.itracker.web.util.ServletContextUtils;
52  import org.itracker.web.util.SessionManager;
53  
54  //TODO: Action Cleanup 
55  
56  /**
57   * 
58   * This seems to be an action that is called always, checking for Permissions,
59   * Authentication and other stuff
60   * 
61   * @author Marky Goldstein
62   * 
63   */
64  public abstract class ItrackerBaseAction extends Action {
65  
66  	private static final Logger log = Logger
67  			.getLogger(ItrackerBaseAction.class);
68  
69  	public ItrackerBaseAction() {
70  		super();
71  	}
72  
73  
74  	protected Map<Integer, Set<PermissionType>> getUserPermissions(
75  			HttpSession session) {
76  		return RequestHelper.getUserPermissions(session);
77  	}
78  
79  	/**
80  	 * TODO: Deprecate and move to {@link org.itracker.web.util.LoginUtilities}
81  	 * 
82  	 * 
83  	 * @param permissionsNeeded
84  	 * @param request
85  	 * @param response
86  	 * @return
87  	 * @throws IOException
88  	 * @throws ServletException
89  	 */
90  	protected boolean hasPermission(int[] permissionsNeeded,
91  			HttpServletRequest request, HttpServletResponse response)
92  			throws IOException, ServletException {
93  		if (isLoggedIn(request, response)) {
94  			HttpSession session = request.getSession(false);
95  			Map<Integer, Set<PermissionType>> permissions = (session == null) ? null
96  					: getUserPermissions(session);
97  			if (!UserUtilities.hasPermission(permissions, permissionsNeeded)) {
98  				return false;
99  			}
100 			return true;
101 		}
102 		return false;
103 	}
104 
105 	/**
106 	 * TODO: Deprecate and move to {@link org.itracker.web.util.LoginUtilities}
107 	 * 
108 	 * @param permissionNeeded
109 	 * @param request
110 	 * @param response
111 	 * @return
112 	 * @throws IOException
113 	 * @throws ServletException
114 	 */
115 	protected boolean hasPermission(int permissionNeeded,
116 			HttpServletRequest request, HttpServletResponse response)
117 			throws IOException, ServletException {
118 //		if (isLoggedIn(request, response)) {
119 			HttpSession session = request.getSession(false);
120 			Map<Integer, Set<PermissionType>> permissionsMap = (session == null) ? null
121 					: getUserPermissions(session);
122 			if (UserUtilities.hasPermission(permissionsMap, permissionNeeded)) {
123 				return true;
124 			}
125 //			return true;
126 //		}
127 		return false;
128 	}
129 
130 	/**
131 	 * 
132 	 * @deprecated move to {@link org.itracker.web.util.LoginUtilities} - no need for actions to check for user being logged in.
133 	 * 
134 	 * @param request
135 	 * @param response
136 	 * @return
137 	 * @throws IOException
138 	 * @throws ServletException
139 	 */
140 	protected boolean isLoggedIn(HttpServletRequest request,
141 			HttpServletResponse response) throws IOException, ServletException {
142 //		
143 //		HttpSession session = request.getSession(false);
144 //		User user = (session == null ? null : (User) session
145 //				.getAttribute(Constants.USER_KEY));
146 //		String login = (user == null ? null : user.getLogin());
147 //
148 //		if (login == null || "".equals(login)) {
149 //			LoginUtilities.checkAutoLogin(request, getAllowSaveLogin());
150 //			return false;
151 //		}
152 		return true;
153 	}
154 
155 	/**
156 	 * 
157 	 * @param request
158 	 *            - request for base-url
159 	 * @return normalized base-url for the request
160 	 */
161 	public String getBaseURL(HttpServletRequest request) {
162 		
163 		String url = getITrackerServices().getConfigurationService().getSystemBaseURL();
164 		if (null == url) {
165 			url = new StringBuffer(request.getScheme()).append("://").append(
166 					request.getServerName()).append(":").append(
167 					request.getServerPort()).append(request.getContextPath())
168 					.toString();
169 
170 			log
171 					.warn("getBaseURL: no base-url is configured, determin from request. ("
172 							+ url + ")");
173 		}
174 		try {
175 			return new URL(url).toExternalForm();
176 		} catch (MalformedURLException e) {
177 			log.warn("failed to get URL normalized, returning manual url: "
178 					+ url, e);
179 		}
180 		return url;
181 	}
182 
183 	/**
184 	 * TODO: Deprecate and move to new static method in a
185 	 * ITrackerServicesFactory-class
186 	 * 
187 	 * @return
188 	 */
189 	protected ITrackerServices getITrackerServices() {
190 		ITrackerServices itrackerServices = ServletContextUtils
191 				.getItrackerServices();
192 		return itrackerServices;
193 	}
194 
195 	/**
196 	 * @deprecated no state information is allowed in actions. use a correct
197 	 *             pattern like request-attributes.
198 	 * @return
199 	 */
200 	public String getName() {
201 		log.warn("getName: is deprecated");
202 		return null;
203 	}
204 
205 	/**
206 	 * @deprecated no state information is allowed in actions. use a correct
207 	 *             pattern like request-attributes.
208 	 * @return
209 	 */
210 	public void setName(String value) {
211 		log.warn("setName: is deprecated");
212 		// name = value;
213 	}
214 
215 	/**
216 	 * @deprecated no state information is allowed in actions. use a correct
217 	 *             pattern like request-attributes.
218 	 * @return
219 	 */
220 	public String getPage() {
221 		log.warn("getPage: is deprecated");
222 		return null;
223 	}
224 
225 	/**
226 	 * @deprecated no state information is allowed in actions. use a correct
227 	 *             pattern like request-attributes.
228 	 * @return
229 	 */
230 	public void setPage(String value) {
231 		log.warn("setPage: is deprecated");
232 		// page = value;
233 	}
234 
235 	/**
236 	 * @deprecated no state information is allowed in actions. use a correct
237 	 *             pattern like request-attributes.
238 	 * @return
239 	 */
240 	public int getPermission() {
241 		log.warn("getPermission: is deprecated");
242 		return -1;
243 	}
244 
245 	/**
246 	 * @deprecated no state information is allowed in actions. use a correct
247 	 *             pattern like request-attributes.
248 	 * @return
249 	 */
250 	public void setPermission(int value) {
251 		log.warn("setPermission: is deprecated");
252 		// permission = value;
253 	}
254 
255 	/**
256 	 * former checkLogin Tag(lib) Code..
257 	 * 
258 	 * TODO: move to static utility-method in {@link LoginUtilities}
259 	 * 
260 	 * TODO: Clean and split this code up, so it is understandable what it does.
261 	 * 
262 	 */
263 	public ActionForward loginRouter(ActionMapping mapping, ActionForm form,
264 			HttpServletRequest request, HttpServletResponse response,
265 			ActionForward thisactionforward) {
266 		ActionForward forward = new ActionForward();
267 		forward = null;
268 		forward = thisactionforward;
269 		boolean hasGlobalPermission;
270 
271 		log
272 				.info("Starting loginRouter (formerly Checklogin tag) proceedure...");
273 		ConfigurationService configurationService = getITrackerServices()
274 				.getConfigurationService();
275 		boolean allowSaveLogin = configurationService.getBooleanProperty(
276 				"allow_save_login", true);
277 
278 		String requestPath = request.getRequestURI();
279 		String redirectURL = request.getRequestURI().substring(
280 				request.getContextPath().length())
281 				+ (request.getQueryString() != null ? "?"
282 						+ request.getQueryString() : "");
283 		log.info("Setting redirectURL = " + redirectURL);
284 
285 		HttpSession session = request.getSession();
286 
287 		try {
288 
289 			// IF NO SESSION IS ACTIVE, THEN DO A REDIRECT (TO THE CURRENT
290 			// PAGE?)...
291 			if (session == null) {
292 				log
293 						.info("No session found, preparing for redirect (not yet implemented");
294 				// pageContext.setAttribute("redirect",
295 				// URLEncoder.encode(redirectURL));
296 				request.setAttribute(Constants.AUTH_REDIRECT_KEY, redirectURL);
297 				// pageContext.forward(getPage());
298 				// RETURN return SKIP_PAGE;
299 				return forward;
300 			}
301 
302 			// GET USER, LOGIN AND PERMISSIONS FROM SESSION
303 			log
304 					.info("Get user, login and permissions from session, if available there.");
305 			User user = (User) session.getAttribute(Constants.USER_KEY);
306 			if (user != null) {
307 				log.info("Found User:" + user.getFirstName() + " "
308 						+ user.getLastName() + " in Session.");
309 			}
310 			String login = (user == null ? null : user.getLogin());
311 			if (login != null) {
312 				log.info("Found Login:" + login + " in Session.");
313 			}
314 			Map<Integer, Set<PermissionType>> permissionsMap = getUserPermissions(session);
315 			if (permissionsMap != null) {
316 				log
317 						.info("Found Permissions:" + permissionsMap
318 								+ " in Session.");
319 			}
320 
321 			// IF THERE IS NO LOGIN, THEN WHAT? THEN TRY A AUTOLOGIN?
322 			log.info("Checkin if login in not null or empty");
323 			if (login == null || login.equals("")) {
324 				log.info("Login is null or empty");
325 				if (LoginUtilities.checkAutoLogin(request, allowSaveLogin)) {
326 					log.info("Trying autologin, because we found a cookie...");
327 					forward = mapping.findForward("autologin");
328 					return forward;
329 
330 				}
331 				// IF WE ARE NOT ON THE LOGIN PAGE...
332 				if (!requestPath.endsWith("/login.do")) {
333 
334 					request.setAttribute("pageTitleKey",
335 							"itracker.web.login.title");
336 					request.setAttribute("pageTitleArg", "");
337 
338 					// logger.logDebug("Request for page " + requestPath + "
339 					// attempted by unknown user.");
340 					request.setAttribute(Constants.AUTH_REDIRECT_KEY,
341 							redirectURL);
342 					// logger.logDebug("Setting redirect url to " +
343 					// request.getAttribute(Constants.AUTH_REDIRECT_KEY));
344 					forward = mapping.findForward("login");
345 					return forward;
346 				}
347 				// IF THERE IS A LOGIN...
348 			} else {
349 				log.info("Login found...: " + login);
350 				if (SessionManager.getSessionNeedsReset(login)) {
351 					// RESET THE SESSION STUFF
352 					log.info("Resetting the Session stuff...");
353 					session.removeAttribute(Constants.USER_KEY);
354 					session.removeAttribute(Constants.PERMISSIONS_KEY);
355 					user = null;
356 					String newLogin = SessionManager.checkRenamedLogin(login);
357 					user = LoginUtilities.setupSession((newLogin == null ? login
358 							: newLogin), request, response);
359 					SessionManager.removeRenamedLogin(login);
360 					if (user == null
361 							|| user.getStatus() != UserUtilities.STATUS_ACTIVE) {
362 						ActionErrors errors = new ActionErrors();
363 						errors.add(ActionMessages.GLOBAL_MESSAGE,
364 								new ActionMessage(
365 										"itracker.web.error.login.inactive"));
366 						request.setAttribute(Globals.ERROR_KEY, errors);
367 						// pageContext.forward(getPage());
368 						// RETURN return SKIP_BODY;
369 						return forward;
370 					}
371 				}
372 
373 				// IF THERE IS NO USER...
374 				log.info("Checkin again if user is null...");
375 				if (user == null) {
376 					request.setAttribute(Constants.AUTH_REDIRECT_KEY,
377 							redirectURL);
378 					// pageContext.forward(getPage());
379 					// RETURN SKIP_PAGE;
380 					return forward;
381 
382 					// IF THERE IS A USER...
383 				} else {
384 					log.info("else...");
385 					log.info("User, yes found...: " + user.getLogin());
386 					log.info("If there is a user...");
387 					permissionsMap = getUserPermissions(session);
388 					SessionManager.updateSessionLastAccess(login);
389 
390 					hasGlobalPermission = true;
391 
392 					// CHECK FOR PERMISSIONS
393 					log
394 							.info("Start check if permissions for this user are found...");
395 					if (getPermission() >= 0) {
396 						log.info("Permissions found...");
397 						if (!UserUtilities.hasPermission(permissionsMap,
398 								getPermission())) {
399 							log
400 									.info("But this user is not allowed by his permissions");
401 							hasGlobalPermission = false;
402 							// check this...
403 							request.setAttribute("hasGlobalPermission",
404 									hasGlobalPermission);
405 							if (!requestPath.endsWith("/unauthorized.do")) {
406 								// pageContext.forward("/unauthorized.do");
407 								// RETURN return SKIP_PAGE;
408 								forward = mapping.findForward("unauthorized");
409 								return forward;
410 							}
411 						}
412 					}
413 
414 				}
415 			}
416 		} catch (Exception e) {
417 			// logger.logError("IOException while checking login. " +
418 			// ioe.getMessage());
419 			// return SKIP_BODY;
420 			return forward;
421 		}
422 
423 		return forward;
424 	}
425 
426 	@Override
427 	public Locale getLocale(HttpServletRequest request) {
428 		Locale locale = super.getLocale(request);
429 		if (null == locale) {
430 			locale = LoginUtilities.getCurrentLocale(request);
431 		}
432 		return locale;
433 	}
434 
435 	/**
436 	 * Log time passed since timestamp startTime was set. After logging, the passed startTime-Date is reset to
437 	 * {@link System#currentTimeMillis()}. This helps on actions performance issues.
438 	 * 
439 	 * 
440 	 * @param message
441 	 * @param startTime
442 	 * @param log
443 	 * @param priority
444 	 */
445 	protected static void logTimeMillies(String message, Date startTime, Logger log,
446 			Level level) {
447 		if (log.isEnabledFor(level)) {
448 			long milliesStart = startTime.getTime();
449 			long milliesEnd = System.currentTimeMillis();
450 			if (null == log) {
451 				log = ItrackerBaseAction.log;
452 			}
453 			if (null == level) {
454 				level = Level.INFO;
455 			}
456 			
457 			log.log(level, new StringBuilder().append("logTimeMillies: ").append(
458 					message).append(" took ").append(milliesEnd - milliesStart)
459 					.append("ms.").toString());
460 	
461 			// reset the timestamp for next log
462 			startTime.setTime(System.currentTimeMillis());
463 		}
464 	}
465 	/**
466 	 * 
467 	 * @TODO: Add Javadocs here: who uses this handleException method? It seems to be called by nobody... please document or clean up.
468 	 *  
469 	 * @param t
470 	 * @param messages
471 	 * @param httpServletRequest
472 	 */
473 	protected void handleException(Throwable t, ActionMessages messages, HttpServletRequest httpServletRequest) {
474 		Object[] params = new Object[]{};
475 		ActionMessage msg = new ActionMessage("itracker.web.error.system.message");
476 		log.debug("An expection has happened in the ItrackerBaseAction with " +msg.getValues()+params.length+" parameters");	
477 		
478 	}
479 
480 }