/**
* Copyright (c) 2009--2015 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.frontend.struts;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.RequestProcessor;
import com.redhat.rhn.common.messaging.MessageQueue;
import com.redhat.rhn.common.security.PermissionException;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.events.TraceBackEvent;
import com.redhat.rhn.manager.acl.AclManager;
/**
* RhnRequestProcessor a custom Struts RequestProcessor that
* intercepts all of our code struts requests
*
* @version $Rev$
*/
public class RhnRequestProcessor extends RequestProcessor {
@Override
protected void processPopulate(HttpServletRequest request, HttpServletResponse response,
ActionForm form, ActionMapping mapping) throws ServletException {
super.processPopulate(request, response, form, mapping);
if (form instanceof ScrubbingDynaActionForm) {
((ScrubbingDynaActionForm) form).scrub();
}
}
/**
* code run before each request for struts. performs rhn
* initialization, such as populating Request scope objects based
* on session. eventually will be where we cleanse formvars as well.
* @param request ServletRequest to process.
* @param response ServletResponse to create.
* @throws IOException thrown if an error occurs reading the stream.
* @throws ServletException thrown if an error occurs in the Servlet.
*/
@Override
public void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
try {
response.addHeader("X-UA-Compatible", "IE=edge,chrome=1");
//Get the mapping so we can see if whether or not we need to process acls
String path = processPath(request, response);
ActionMapping originalMapping = (ActionMapping)
moduleConfig.findActionConfig(path);
if (originalMapping != null && originalMapping instanceof RhnActionMapping) {
//we need to process a list of acls
RhnActionMapping mapping = (RhnActionMapping) originalMapping;
// if postRequired="true", make sure we're using POST
if (mapping.postRequired() && !request.getMethod().equals("POST")) {
// send HTTP 405 if POST wasn't used
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
RequestContext requestContext = new RequestContext(request);
// if postRequiredIfSubmitted="true", make sure we're using POST
if (mapping.postRequiredIfSubmitted() && requestContext.isSubmitted() &&
!request.getMethod().equals("POST")) {
// send HTTP 405 if POST wasn't used
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
if (!AclManager.hasAcl(mapping.getAcls(), request, mapping.getMixins())) {
//an acl evaluated to false
PermissionException e = new PermissionException("Missing Acl: " +
mapping.getAcls() + " when accessing " + request.getRequestURI());
log.error(e.getMessage());
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
request.setAttribute("error", e);
//forward to permissions error page
doForward("/errors/Permission.do", request, response);
//exit method
return;
}
}
//now that we're done with rhn stuff, call RequestProcessor.process()
super.process(request, response);
}
catch (IOException se) {
sendErrorEmail(request, se);
throw se;
}
catch (ServletException se) {
fixCause(se);
sendErrorEmail(request, se);
throw se;
}
catch (RuntimeException re) {
if (re.getCause() == null) {
sendErrorEmail(request, re);
}
else {
sendErrorEmail(request, re.getCause());
}
throw re;
}
}
private void fixCause(ServletException e) {
// ServletException has a rootCause that is separate from
// Throwable.cause. Try and set Throwable.cause to ServletException.rootCause
// for the chain of exceptions starting with e.rootCause
do {
Throwable cause = e.getRootCause();
if (cause != null && e.getCause() == null) {
e.initCause(cause);
}
if (cause instanceof ServletException) {
e = (ServletException) cause;
}
else {
e = null;
}
} while (e != null);
}
// Send an error email when an Action generates an Exception
private void sendErrorEmail(HttpServletRequest request, Throwable e) {
TraceBackEvent evt = new TraceBackEvent();
RequestContext requestContext = new RequestContext(request);
User usr = requestContext.getCurrentUser();
evt.setUser(usr);
evt.setRequest(request);
evt.setException(e);
MessageQueue.publish(evt);
}
}