NIHVIVO-3118 Send an email to the site administrator in case of an error on a Freemarker page if the user is not authorized to view the error details.

This commit is contained in:
ryounes 2011-08-12 00:03:39 +00:00
parent 6bb9831bda
commit 044c4a0674
4 changed files with 131 additions and 30 deletions

View file

@ -2,9 +2,12 @@
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import static javax.mail.Message.RecipientType.TO;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -21,6 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOwnAcc
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseMiscellaneousAdminPages;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException;
@ -32,6 +36,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Red
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory;
import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.User;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.menu.MainMenu;
import freemarker.ext.beans.BeansWrapper;
@ -50,14 +55,22 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
public static final String BODY_TEMPLATE_TYPE = "body";
protected enum Template {
STANDARD_ERROR("error-standard.ftl"),
ERROR_MESSAGE("error-message.ftl"),
TITLED_ERROR_MESSAGE("error-titled.ftl"),
ERROR_DISPLAY("error-display.ftl"),
MESSAGE("message.ftl"),
TITLED_MESSAGE("message-titled.ftl"),
SETUP("setup.ftl"),
PAGE_DEFAULT("page.ftl"),
SETUP("setup.ftl");
// error templates
ERROR_DISPLAY("error-display.ftl"),
ERROR_EMAIL("error-email.ftl"),
ERROR_MESSAGE("error-message.ftl"),
STANDARD_ERROR("error-standard.ftl"),
TITLED_ERROR_MESSAGE("error-titled.ftl"),
// message templates
MESSAGE("message.ftl"),
TITLED_MESSAGE("message-titled.ftl");
private final String filename;
@ -105,25 +118,61 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
}
}
/** In case of a processing error, display an error page. To an authorized user, the page displays
* details of the error. Otherwise, these details are sent to the site administrator.
*/
protected void handleException(VitroRequest vreq, HttpServletResponse response, Throwable t) throws ServletException {
try {
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
ExceptionResponseValues rv;
Map<String, Object> templateMap = new HashMap<String, Object>();
String templateName = Template.ERROR_DISPLAY.toString();
if (PolicyHelper.isAuthorizedForActions(vreq, new UseMiscellaneousAdminPages())) {
Map<String, Object> map = new HashMap<String, Object>();
Map<String, String> errorData = new HashMap<String, String>();
errorData.put("errorMessage", t.getMessage());
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
errorData.put("stackTrace", sw.toString());
map.put("errorData", errorData);
rv = new ExceptionResponseValues(templateName, map, t, statusCode);
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
// adminErrorData will be viewable only by an admin, either on the
// page or in an email.
Map<String, Object> adminErrorData = new HashMap<String, Object>();
StringBuffer requestedUrl = vreq.getRequestURL();
String queryString = vreq.getQueryString();
if (queryString != null) {
requestedUrl.append(queryString);
}
adminErrorData.put("requestedUrl", requestedUrl);
String errorMessage = t.getMessage();
adminErrorData.put("errorMessage", errorMessage);
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
adminErrorData.put("stackTrace", stackTrace);
adminErrorData.put("datetime", new Date());
templateMap.put("errorOnHomePage", this instanceof HomePageController);
boolean sentEmail = false;
// If the user is authorized, display the error data on the page
if (PolicyHelper.isAuthorizedForActions(vreq, new UseMiscellaneousAdminPages())) {
templateMap.put("adminErrorData", adminErrorData);
// Else send the data to the site administrator
} else {
rv = new ExceptionResponseValues(templateName, t, statusCode);
}
FreemarkerEmailMessage email = FreemarkerEmailFactory.createNewMessage(vreq);
String recipient = ConfigurationProperties.getBean(getServletContext())
.getProperty("email.replyTo");
email.addRecipient(TO, recipient);
email.setTemplate(Template.ERROR_EMAIL.toString());
email.setBodyMap(adminErrorData);
email.processTemplate();
sentEmail = email.send();
}
templateMap.put("sentEmail", sentEmail);
ExceptionResponseValues rv = new ExceptionResponseValues(templateName, templateMap, t, statusCode);
doResponse(vreq, response, rv);
} catch (TemplateProcessingException e) {
throw new ServletException();
}

View file

@ -167,7 +167,7 @@ public class FreemarkerEmailMessage {
}
}
public void send() {
public boolean send() {
try {
MimeMessage msg = new MimeMessage(session);
msg.setReplyTo(new Address[] { replyToAddress });
@ -204,9 +204,10 @@ public class FreemarkerEmailMessage {
msg.setSentDate(new Date());
Transport.send(msg);
return true;
} catch (MessagingException e) {
log.error("Failed to send message.", e);
return false;
}
}

View file

@ -4,20 +4,22 @@
<p>
There was an error in the system.
<#-- This error has been reported to the site administrator. -->
<#if sentEmail>
This error has been reported to the site administrator.
</#if>
</p>
<#if errorData??> <#-- view for site administrators -->
<#if errorData.errorMessage?has_content>
<p><strong>Error message:</strong> ${errorData.errorMessage}</p>
<#if adminErrorData??> <#-- view for site administrators -->
<#if adminErrorData.errorMessage?has_content>
<p><strong>Error message:</strong> ${adminErrorData.errorMessage}</p>
</#if>
<#if errorData.stackTrace?has_content>
<#if adminErrorData.stackTrace?has_content>
<div>
<p><strong>Stack trace</strong> (full trace available in the vivo log):</p>
${errorData.stackTrace}
${adminErrorData.stackTrace}
</div>
</#if>
<#elseif ! urls.currentPage?ends_with("home")> <#-- view for other users -->
<#elseif ! errorOnHomePage> <#-- view for other users -->
<p>Return to the <a href="${urls.home}">home page</a>.</p>
</#if>

View file

@ -0,0 +1,49 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for email message sent to site administrator when an error occurs on the site. -->
<#assign subject = "An error occurred on the VIVO site" />
<#assign datetime = datetime?string("yyyy-MM-dd HH:mm:ss zzz")>
<#assign html>
<html>
<head>
<title>${subject}</title>
</head>
<body>
<p>
An error occurred on your VIVO site at ${datetime}.
</p>
<p>
<strong>Requested url:</strong> ${requestedUrl}.
</p>
<p>
<strong>Error message:</strong> ${errorMessage}.
</p>
<p>
<strong>Stack trace</strong> (full trace available in the vivo log):
</p>
<div>${stackTrace}</div>
</body>
</html>
</#assign>
<#assign text>
An error occurred on your VIVO site at ${datetime}.
Requested url: ${requestedUrl}.
Error message: ${errorMessage}.
Stack trace (full trace available in the vivo log):
${stackTrace}
</#assign>
<@email subject=subject html=html text=text />