From cd439b8aaa7f6aac3d2096a6c6514e77d545e486 Mon Sep 17 00:00:00 2001 From: ryounes Date: Mon, 13 Jun 2011 16:04:25 +0000 Subject: [PATCH 01/47] Remove old ContactMailServlet and servlet mappings. --- webapp/config/web.xml | 12 - .../webapp/controller/ContactMailServlet.java | 352 ------------------ .../NameStatementTemplateModel.java | 7 - 3 files changed, 371 deletions(-) delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ContactMailServlet.java diff --git a/webapp/config/web.xml b/webapp/config/web.xml index 31e263e37..dd354a578 100644 --- a/webapp/config/web.xml +++ b/webapp/config/web.xml @@ -1020,18 +1020,6 @@ /dwr/* - - - sendmail - edu.cornell.mannlib.vitro.webapp.controller.ContactMailServlet - 5 - - - sendmail - /sendmail - - - sendMail edu.cornell.mannlib.vitro.webapp.controller.freemarker.ContactMailController diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ContactMailServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ContactMailServlet.java deleted file mode 100644 index 134717ed7..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ContactMailServlet.java +++ /dev/null @@ -1,352 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.controller; - -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Calendar; -import java.util.Date; - -import javax.mail.Message; -import javax.mail.MessagingException; -import javax.mail.SendFailedException; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.AddressException; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean; -import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory; - -public class ContactMailServlet extends VitroHttpServlet { - - private static final Log log = LogFactory.getLog(ContactMailServlet.class); - - private final static String CONFIRM_PAGE = "/templates/parts/thankyou.jsp"; - private final static String ERR_PAGE = "/templates/parts/contact_err.jsp"; - private final static String SPAM_MESSAGE = "Your message was flagged as spam."; - private final static String EMAIL_BACKUP_FILE_PATH = "/WEB-INF/LatestMessage.html"; - - private final static String WEB_USERNAME_PARAM = "webusername"; - private final static String WEB_USEREMAIL_PARAM = "webuseremail"; - private final static String COMMENTS_PARAM = "s34gfd88p9x1"; - - @Override - public void doGet( HttpServletRequest request, HttpServletResponse response ) - throws ServletException, IOException { - - VitroRequest vreq = new VitroRequest(request); - - ApplicationBean appBean = vreq.getAppBean(); - - String statusMsg = null; // holds the error status - - if (!FreemarkerEmailFactory.isConfigured(vreq)) { - statusMsg = "This application has not yet been configured to send mail. " - + "Email properties must be specified in the configuration properties file."; - redirectToError(response, statusMsg); - return; - } - - String webusername = vreq.getParameter(WEB_USERNAME_PARAM); - String webuseremail = vreq.getParameter(WEB_USEREMAIL_PARAM); - String comments = vreq.getParameter(COMMENTS_PARAM); - - String validationMessage = validateInput(webusername, webuseremail, - comments); - if (validationMessage != null) { - redirectToError(response, validationMessage); - return; - } - webusername = webusername.trim(); - webuseremail = webuseremail.trim(); - comments = comments.trim(); - - String spamReason = null; - - String originalReferer = (String) request.getSession() - .getAttribute("commentsFormReferer"); - if (originalReferer != null) { - request.getSession().removeAttribute("commentsFormReferer"); - /* does not support legitimate clients that don't send the Referer header - String referer = request.getHeader("Referer"); - if (referer == null || - (referer.indexOf("comments") <0 - && referer.indexOf("correction") <0) ) { - spamReason = "The form was not submitted from the " + - "Contact Us or Corrections page."; - statusMsg = SPAM_MESSAGE; - } - */ - } else { - originalReferer = "none"; - } - - if (spamReason == null) { - spamReason = checkForSpam(comments); - if (spamReason != null) { - statusMsg = SPAM_MESSAGE; - } - } - - String formType = vreq.getParameter("DeliveryType"); - String[] deliverToArray = null; - int recipientCount = 0; - String deliveryfrom = null; - - if ("comment".equals(formType)) { - if (appBean.getContactMail() == null || appBean.getContactMail().trim().length()==0) { - log.error("No contact mail address defined in current application"); - throw new Error( - "To establish the Contact Us mail capability the system administrators must " - + "specify an email address in the current portal."); - } else { - deliverToArray = appBean.getContactMail().split(","); - } - deliveryfrom = "Message from the "+appBean.getApplicationName()+" Contact Form"; - } else if ("correction".equals(formType)) { - if (appBean.getCorrectionMail() == null || appBean.getCorrectionMail().trim().length()==0) { - log.error("Expecting one or more correction email addresses to be specified in current application; will attempt to use contact mail address"); - if (appBean.getContactMail() == null || appBean.getContactMail().trim().length()==0) { - log.error("No contact mail address or correction mail address defined in current application"); - } else { - deliverToArray = appBean.getContactMail().split(","); - } - } else { - deliverToArray = appBean.getCorrectionMail().split(","); - } - deliveryfrom = "Message from the "+appBean.getApplicationName()+" Correction Form (ARMANN-nospam)"; - } else { - deliverToArray = appBean.getContactMail().split(","); - statusMsg = SPAM_MESSAGE ; - spamReason = "The form specifies no delivery type."; - } - recipientCount=(deliverToArray == null) ? 0 : deliverToArray.length; - if (recipientCount == 0) { - log.error("recipientCount is 0 when DeliveryType specified as \""+formType+"\""); - throw new Error( - "To establish the Contact Us mail capability the system administrators must " - + "specify at least one email address in the current portal."); - } - - String msgText = composeEmail(webusername, webuseremail, comments, - deliveryfrom, originalReferer, request.getRemoteAddr()); - - // debugging - PrintWriter outFile = new PrintWriter - (new FileWriter(request.getSession().getServletContext() - .getRealPath(EMAIL_BACKUP_FILE_PATH),true)); //autoflush - writeBackupCopy(outFile, msgText, spamReason); - - Session s = FreemarkerEmailFactory.getEmailSession(vreq); - //s.setDebug(true); - try { - - if (spamReason == null) { - sendMessage(s, webuseremail, deliverToArray, deliveryfrom, - recipientCount, msgText); - } - - } catch (AddressException e) { - statusMsg = "Please supply a valid email address."; - outFile.println( statusMsg ); - outFile.println( e.getMessage() ); - } catch (SendFailedException e) { - statusMsg = "The system was unable to deliver your mail. Please try again later. [SEND FAILED]"; - outFile.println( statusMsg ); - outFile.println( e.getMessage() ); - } catch (MessagingException e) { - statusMsg = "The system was unable to deliver your mail. Please try again later. [MESSAGING]"; - outFile.println( statusMsg ); - outFile.println( e.getMessage() ); - e.printStackTrace(); - } - - outFile.flush(); - outFile.close(); - - // Redirect to the appropriate confirmation page - if (statusMsg == null && spamReason == null) { - // message was sent successfully - redirectToConfirmation(response, statusMsg); - } else { - // exception occurred - redirectToError( response, statusMsg); - } - - } - - @Override - public void doPost( HttpServletRequest request, HttpServletResponse response ) - throws ServletException, IOException - { - doGet( request, response ); - } - - private void redirectToConfirmation(HttpServletResponse response, - String statusMsg) throws IOException { - response.sendRedirect( "test?bodyJsp=" + CONFIRM_PAGE + "&home=" ); - } - - private void redirectToError(HttpServletResponse response, String statusMsg) - throws IOException { - response.sendRedirect("test?bodyJsp=" + ERR_PAGE + "&ERR=" + statusMsg); - } - - /** Intended to mangle url so it can get through spam filtering - * http://host/dir/servlet?param=value -> host: dir/servlet?param=value */ - public String stripProtocol( String in ){ - if( in == null ) - return ""; - else - return in.replaceAll("http://", "host: " ); - } - - private String composeEmail(String webusername, String webuseremail, - String comments, String deliveryfrom, - String originalReferer, String ipAddr) { - - StringBuffer msgBuf = new StringBuffer(); - // contains the intro copy for the body of the email message - - String lineSeparator = System.getProperty("line.separator"); - // \r\n on windows, \n on unix - - // from MyLibrary - msgBuf.setLength(0); - msgBuf.append("Content-Type: text/html; charset='us-ascii'" + lineSeparator); - msgBuf.append("" + lineSeparator ); - msgBuf.append("" + lineSeparator ); - msgBuf.append("" + lineSeparator ); - msgBuf.append("" + deliveryfrom + "" + lineSeparator ); - msgBuf.append("" + lineSeparator ); - msgBuf.append("" + lineSeparator ); - msgBuf.append("

" + deliveryfrom + "

" + lineSeparator ); - msgBuf.append("

From: "+webusername +" (" + webuseremail + ")" + - " at IP address " + ipAddr + "

"+lineSeparator); - - if (!(originalReferer == null || originalReferer.equals("none"))){ - //The spam filter that is being used by the listsrv is rejecting likely viewing page " + stripProtocol(originalReferer) ); - msgBuf.append("

likely viewing page " + originalReferer ); - } - - msgBuf.append(lineSeparator + "

Comments:

" + lineSeparator ); - if (comments==null || comments.equals("")) { - msgBuf.append("

BLANK MESSAGE

"); - } else { - msgBuf.append("

"+comments+"

"); - } - msgBuf.append("" + lineSeparator ); - msgBuf.append("" + lineSeparator ); - - return msgBuf.toString(); - - } - - private void writeBackupCopy(PrintWriter outFile, String msgText, - String spamReason) { - Calendar cal = Calendar.getInstance(); - outFile.println("
"); - outFile.println(); - outFile.println("

"+cal.getTime()+"

"); - outFile.println(); - if (spamReason != null) { - outFile.println("

REJECTED - SPAM

"); - outFile.println("

"+spamReason+"

"); - outFile.println(); - } - outFile.print( msgText ); - outFile.println(); - outFile.println(); - outFile.flush(); - // outFile.close(); - } - - private void sendMessage(Session s, String webuseremail, - String[] deliverToArray, String deliveryfrom, int recipientCount, - String msgText) - throws AddressException, SendFailedException, MessagingException { - // Construct the message - MimeMessage msg = new MimeMessage( s ); - //System.out.println("trying to send message from servlet"); - - // Set the from address - msg.setFrom( new InternetAddress( webuseremail )); - - // Set the recipient address - - if (recipientCount>0){ - InternetAddress[] address=new InternetAddress[recipientCount]; - for (int i=0; i -1 - || comments.indexOf("[/URL]") > -1 - || comments.indexOf("[url=") > -1 - || comments.indexOf("[URL=") > -1)) { - return "The message contained blog link markup."; - } - - /* if message is absurdly short, treat as blog spam */ - if (comments.length()<15) { - return "The message was too short."; - } - - return null; - - } -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java index d00e5041f..f9d9480eb 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/NameStatementTemplateModel.java @@ -2,26 +2,19 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; -import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openrdf.model.URI; import org.openrdf.model.impl.URIImpl; -import com.hp.hpl.jena.rdf.model.Literal; - import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; -import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropDataPropStmt; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.EditDataPropStmt; import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; import edu.cornell.mannlib.vitro.webapp.edit.EditLiteral; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.RdfLiteralHash; From e5669be19ed66d685880bd1d6f52b02643128468 Mon Sep 17 00:00:00 2001 From: j2blake Date: Mon, 13 Jun 2011 16:29:56 +0000 Subject: [PATCH 02/47] NIHVIVO-2696 allow the Authenticator to invalidate the cache of Identifiers. --- .../vitro/webapp/auth/identifier/RequestIdentifiers.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/identifier/RequestIdentifiers.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/identifier/RequestIdentifiers.java index 9eff6e6f2..d94433bc5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/identifier/RequestIdentifiers.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/identifier/RequestIdentifiers.java @@ -46,4 +46,11 @@ public class RequestIdentifiers { return (IdentifierBundle) obj; } + /** + * The login status has changed, so discard the cached Identifiers. + */ + public static void resetIdentifiers(ServletRequest request) { + request.removeAttribute(ATTRIBUTE_ID_BUNDLE); + } + } From be4204f2c23f668f8d437847a00fddee5d937b47 Mon Sep 17 00:00:00 2001 From: manolobevia Date: Mon, 13 Jun 2011 16:40:56 +0000 Subject: [PATCH 03/47] NIHVIVO-2280: Removed extra line break --- webapp/web/js/account/accountUtils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/webapp/web/js/account/accountUtils.js b/webapp/web/js/account/accountUtils.js index 6f1aa0d69..786ea38c9 100644 --- a/webapp/web/js/account/accountUtils.js +++ b/webapp/web/js/account/accountUtils.js @@ -6,7 +6,6 @@ function changeAction(form, url) { return true; } - $(document).ready(function(){ //Accounts per page From f3a56d0f4ca3e54ff8638f9740c563a8cde722a4 Mon Sep 17 00:00:00 2001 From: j2blake Date: Mon, 13 Jun 2011 16:50:43 +0000 Subject: [PATCH 04/47] Comments --- .../vitro/webapp/controller/login/LoginProcessBean.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/login/LoginProcessBean.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/login/LoginProcessBean.java index 28a30115e..80b28c2d8 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/login/LoginProcessBean.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/login/LoginProcessBean.java @@ -14,6 +14,14 @@ import org.apache.commons.logging.LogFactory; /** * Where are we in the process of logging on? What message should we show to the * user? + * + * TODO: the contents loginPageUrl is not explicitly defined, but it is assumed + * to be either null, absolute, or relative to the host. It would be better if + * it were explicitly defined, and either null, absolute or relative to the + * context path. Then, the context path could be applied when the URL is used. + * Later for that. + * + * TODO: similar for afterLoginUrl, I presume. */ public class LoginProcessBean { private static final Log log = LogFactory.getLog(LoginProcessBean.class); From 26ed55027dadb9165b71dc29db6cffac170df20e Mon Sep 17 00:00:00 2001 From: manolobevia Date: Mon, 13 Jun 2011 17:02:55 +0000 Subject: [PATCH 05/47] NIHVIVO-2280: Worked on Add new account page: Added breadcrumbs, changed text size for radio buttons, and added style for Cancel button. --- .../templates/freemarker/body/accounts/userAccounts-add.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl index 9ec0d64a5..c6d4809c6 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl @@ -2,7 +2,7 @@ <#-- Template for adding a user account --> -

Add new account

+
<#if errorEmailIsEmpty??> <#assign errorMessage = "You must supply an email address." /> @@ -93,7 +93,7 @@

- or Cancel + or Cancel

* required fields

From 22507b11c083dba2778342c09e53e0d76d8efd88 Mon Sep 17 00:00:00 2001 From: j2blake Date: Mon, 13 Jun 2011 17:44:42 +0000 Subject: [PATCH 06/47] NIHVIVO-2696 de-couple the LoginRedirector from the LoginProcessBean. --- .../user/UserAccountsUserController.java | 2 +- .../authenticate/LoginExternalAuthReturn.java | 20 +++++++++---- .../authenticate/LoginRedirector.java | 10 ++----- .../webapp/controller/edit/Authenticate.java | 29 +++++++++++++++++-- 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java index 7628362ac..322dd6c2b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java @@ -133,7 +133,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet { } private ResponseValues showLoginRedirection(VitroRequest vreq) { - LoginRedirector lr = new LoginRedirector(vreq); + LoginRedirector lr = new LoginRedirector(vreq, null); DisplayMessage.setMessage(vreq, lr.assembleWelcomeMessage()); String uri = lr.getRedirectionUriForLoggedInUser(); return new RedirectResponseValues(uri); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java index 8b525f6fe..d970db6cd 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java @@ -16,6 +16,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; +import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean; /** * Handle the return from the external authorization login server. If we are @@ -36,6 +37,13 @@ public class LoginExternalAuthReturn extends BaseLoginServlet { * - User corresponds to a User acocunt. Record the login. * - User corresponds to an Individual (self-editor). * - User is not recognized. + * + * On entry, we expect to find: + * - A LoginProcessBean, which will give us the afterLoginUrl if the login + * succeeds. + * - A referrer URL, to which we will redirect if the login fails. + * TODO: is this equal to LoginProcessBean.getLoginPageUrl()? + * These are removed on exit. * */ @Override @@ -49,6 +57,9 @@ public class LoginExternalAuthReturn extends BaseLoginServlet { MESSAGE_LOGIN_FAILED); return; } + + String afterLoginUrl = LoginProcessBean.getBean(req).getAfterLoginUrl(); + removeLoginProcessArtifacts(req); UserAccount userAccount = getAuthenticator(req) .getAccountForExternalAuth(externalAuthId); @@ -56,8 +67,7 @@ public class LoginExternalAuthReturn extends BaseLoginServlet { log.debug("Logging in as " + userAccount.getUri()); getAuthenticator(req).recordLoginAgainstUserAccount(userAccount, AuthenticationSource.EXTERNAL); - removeLoginProcessArtifacts(req); - new LoginRedirector(req).redirectLoggedInUser(resp); + new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp); return; } @@ -70,19 +80,19 @@ public class LoginExternalAuthReturn extends BaseLoginServlet { String uri = associatedUris.get(0); getAuthenticator(req).recordLoginWithoutUserAccount(uri); - removeLoginProcessArtifacts(req); - new LoginRedirector(req).redirectLoggedInUser(resp); + new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp); return; } log.debug("User is not recognized: " + externalAuthId); removeLoginProcessArtifacts(req); - new LoginRedirector(req).redirectUnrecognizedExternalUser(resp, + new LoginRedirector(req, afterLoginUrl).redirectUnrecognizedExternalUser(resp, externalAuthId); } private void removeLoginProcessArtifacts(HttpServletRequest req) { req.getSession().removeAttribute(ATTRIBUTE_REFERRER); + LoginProcessBean.removeBean(req); } @Override diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java index 57c9375f1..f25db5be9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java @@ -20,7 +20,6 @@ import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel; import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean; /** * A user has just completed the login process. What page do we direct them to? @@ -34,15 +33,12 @@ public class LoginRedirector { private final String uriOfAssociatedIndividual; private final String afterLoginPage; - public LoginRedirector(HttpServletRequest request) { + public LoginRedirector(HttpServletRequest request, String afterLoginPage) { this.request = request; this.session = request.getSession(); + this.afterLoginPage = afterLoginPage; uriOfAssociatedIndividual = getAssociatedIndividualUri(); - - LoginProcessBean processBean = LoginProcessBean.getBean(request); - log.debug("process bean is: " + processBean); - afterLoginPage = processBean.getAfterLoginUrl(); } /** Is there an Individual associated with this user? */ @@ -106,7 +102,6 @@ public class LoginRedirector { try { DisplayMessage.setMessage(request, assembleWelcomeMessage()); response.sendRedirect(getRedirectionUriForLoggedInUser()); - LoginProcessBean.removeBean(request); } catch (IOException e) { log.debug("Problem with re-direction", e); response.sendRedirect(getApplicationHomePageUrl()); @@ -142,7 +137,6 @@ public class LoginRedirector { throws IOException { try { response.sendRedirect(getRedirectionUriForCancellingUser()); - LoginProcessBean.removeBean(request); } catch (IOException e) { log.debug("Problem with re-direction", e); response.sendRedirect(getApplicationHomePageUrl()); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java index 9bf9847f6..1949009e6 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java @@ -124,7 +124,7 @@ public class Authenticate extends VitroHttpServlet { // Send them on their way. switch (exitState) { case NOWHERE: - new LoginRedirector(vreq).redirectCancellingUser(response); + showLoginCanceled(response, vreq); break; case LOGGING_IN: showLoginScreen(vreq, response); @@ -133,7 +133,7 @@ public class Authenticate extends VitroHttpServlet { showLoginScreen(vreq, response); break; default: // LOGGED_IN: - new LoginRedirector(vreq).redirectLoggedInUser(response); + showLoginComplete(response, vreq); break; } } catch (Exception e) { @@ -477,6 +477,31 @@ public class Authenticate extends VitroHttpServlet { response.sendRedirect(loginProcessPage); return; } + + /** + * Exit: user has completed the login. Redirect appropriately and clear the bean. + */ + private void showLoginComplete(HttpServletResponse response, + VitroRequest vreq) throws IOException { + getLoginRedirector(vreq).redirectLoggedInUser(response); + LoginProcessBean.removeBean(vreq); + } + + /** + * Exit: user has canceled. Redirect and clear the bean. + */ + private void showLoginCanceled(HttpServletResponse response, + VitroRequest vreq) throws IOException { + getLoginRedirector(vreq).redirectCancellingUser(response); + LoginProcessBean.removeBean(vreq); + } + + private LoginRedirector getLoginRedirector(VitroRequest vreq) { + String afterLoginUrl = LoginProcessBean.getBean(vreq).getAfterLoginUrl(); + return new LoginRedirector(vreq, afterLoginUrl); + } + + /** Get a reference to the Authenticator. */ private Authenticator getAuthenticator(HttpServletRequest request) { From 29ab2290b698a5c3d2683bbc52a296f81e5a9753 Mon Sep 17 00:00:00 2001 From: brianjlowe Date: Mon, 13 Jun 2011 17:55:13 +0000 Subject: [PATCH 07/47] NIHVIVO-2316 removed unnecessary graph variables in queries --- .../dao/jena/DataPropertyStatementDaoSDB.java | 6 +-- .../vitro/webapp/dao/jena/IndividualSDB.java | 44 ++++++------------- .../web/templates/edit/specific/ents_edit.jsp | 12 ++--- 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java index a93ac88ae..dac869b54 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java @@ -57,15 +57,13 @@ public class DataPropertyStatementDaoSDB extends DataPropertyStatementDaoJena } else { - String[] graphVars = { "?g" }; String query = "CONSTRUCT { \n" + " <" + entity.getURI() + "> ?p ?o . \n" + - "} WHERE { GRAPH ?g { \n" + + "} WHERE { \n" + " <" + entity.getURI() + "> ?p ?o . \n" + " FILTER(isLiteral(?o)) \n" + - WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) + - "} }" ; + "}" ; Model results = null; DatasetWrapper w = dwf.getDatasetWrapper(); Dataset dataset = w.getDataset(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java index 96cedd1c2..95216e798 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java @@ -395,8 +395,8 @@ public class IndividualSDB extends IndividualImpl implements Individual { String[] graphVars = { "?g" }; String queryStr = "CONSTRUCT { <"+ind.getURI()+"> <" + propertyURI + "> ?value } \n" + - "WHERE { GRAPH ?g { \n" + - "<" + ind.getURI() +"> <" + propertyURI + "> ?value } \n" + + "WHERE { \n" + + "<" + ind.getURI() +"> <" + propertyURI + "> ?value \n" + WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) + "\n} "; Query query = QueryFactory.create(queryStr); @@ -502,14 +502,11 @@ public class IndividualSDB extends IndividualImpl implements Individual { if( _hasThumb != null ){ return _hasThumb; }else{ - String[] graphVars = { "?g" }; String ask = - "ASK { GRAPH ?g " + - " { <" + individualURI + "> ?mainImage . \n" + - " ?mainImage ?thumbImage . }\n" + - WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) + - "}"; - DatasetWrapper w = getDatasetWrapper(); + "ASK { " + + " <" + individualURI + "> ?mainImage . \n" + + " ?mainImage ?thumbImage . }\n" ; + DatasetWrapper w = getDatasetWrapper(); Dataset dataset = w.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); try{ @@ -552,10 +549,8 @@ public class IndividualSDB extends IndividualImpl implements Individual { Dataset dataset = w.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); try { - String graphVars[] = { "?g" }; StringBuffer selectPrimaryLinkQueryBuff = new StringBuffer().append( - "SELECT ?url ?anchor \n" ).append( - "WHERE{ GRAPH ?g { \n " ).append( + "SELECT ?url ?anchor \n" ).append(" WHERE { \n").append( " <" + this.individualURI + "> ").append( "<" + VitroVocabulary.PRIMARY_LINK + "> " ).append( "?link . \n").append( @@ -563,9 +558,7 @@ public class IndividualSDB extends IndividualImpl implements Individual { ).append( " ?link <" + VitroVocabulary.LINK_ANCHOR + "> ?anchor . \n" ).append( - "} \n") - .append(WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode)) - .append("}"); + "} \n"); QueryExecution qexec = QueryExecutionFactory.create( QueryFactory.create(selectPrimaryLinkQueryBuff.toString()) , dataset); @@ -678,12 +671,9 @@ public class IndividualSDB extends IndividualImpl implements Individual { Dataset dataset = w.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); try { - String[] graphVars = { "?g" }; String valuesOfProperty = - "CONSTRUCT{<" + this.individualURI + "> <" + propertyURI + "> ?object}" + - "WHERE{ GRAPH ?g { <" + this.individualURI + "> <" + propertyURI + "> ?object} \n" + - WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) + - "}"; + "CONSTRUCT{ <" + this.individualURI + "> <" + propertyURI + "> ?object }" + + "WHERE{ <" + this.individualURI + "> <" + propertyURI + "> ?object } \n"; tempModel = QueryExecutionFactory.create(QueryFactory.create(valuesOfProperty), dataset).execConstruct(); ontModel.add(tempModel.listStatements()); Resource ontRes = ontModel.getResource(this.individualURI); @@ -727,13 +717,10 @@ public class IndividualSDB extends IndividualImpl implements Individual { Dataset dataset = w.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); try { - String[] graphVars = { "?g" }; String valuesOfProperty = "SELECT ?object" + - "WHERE{ GRAPH ?g { <" + this.individualURI + "> <" + - propertyURI + "> ?object} \n" + - WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) + - "}"; + "WHERE{ <" + this.individualURI + "> <" + + propertyURI + "> ?object } \n"; ResultSet values = QueryExecutionFactory.create( QueryFactory.create(valuesOfProperty), dataset) .execSelect(); @@ -767,13 +754,10 @@ public class IndividualSDB extends IndividualImpl implements Individual { Dataset dataset = w.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); try { - String[] graphVars = { "?g" }; String valueOfProperty = "SELECT ?object " + - "WHERE{ GRAPH ?g { <" + this.individualURI + "> <" + - propertyURI + "> ?object} \n" + - WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) + - "}"; + "WHERE{ <" + this.individualURI + "> <" + + propertyURI + "> ?object } \n"; QueryExecution qe = QueryExecutionFactory.create( QueryFactory.create(valueOfProperty), dataset); try { diff --git a/webapp/web/templates/edit/specific/ents_edit.jsp b/webapp/web/templates/edit/specific/ents_edit.jsp index 32b09295d..1a9ff77c6 100644 --- a/webapp/web/templates/edit/specific/ents_edit.jsp +++ b/webapp/web/templates/edit/specific/ents_edit.jsp @@ -34,13 +34,13 @@
@@ -51,13 +51,13 @@ From 1415323fde9f450f83656b6fa5e4eee5b3866b6a Mon Sep 17 00:00:00 2001 From: manolobevia Date: Mon, 13 Jun 2011 18:12:18 +0000 Subject: [PATCH 08/47] NIHVIVO-2280: Styled 'create new password' page for new user accounts. --- webapp/web/css/edit.css | 1 + .../accounts/userAccounts-createPassword.ftl | 29 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/webapp/web/css/edit.css b/webapp/web/css/edit.css index ad2099f6f..7ae7dd1d4 100644 --- a/webapp/web/css/edit.css +++ b/webapp/web/css/edit.css @@ -359,4 +359,5 @@ div.sparqlform .parenthetical { .note { font-size: .8em; line-height: 1.3em; + color: #7f8993; } \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-createPassword.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-createPassword.ftl index 2b75cff0c..9c1f93f5c 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-createPassword.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-createPassword.ftl @@ -3,7 +3,6 @@ <#-- Template for adding a user account -->

Create your Password

- <#if errorPasswordIsEmpty??> <#assign errorMessage = "No password supplied." /> @@ -24,26 +23,24 @@
-
- Please enter your new password for ${userAccount.emailAddress} +

Please enter your new password for ${userAccount.emailAddress}

- - - + + + + + + - - - -

Minimum of ${minimumLength} characters in length.

+

Minimum of ${minimumLength} characters in length.

- - + + - +

-

* required fields

- -
+

* required fields

+
${stylesheets.add('')} \ No newline at end of file From b4891d2139700c251b4600f73ac93658330573d9 Mon Sep 17 00:00:00 2001 From: brianjlowe Date: Mon, 13 Jun 2011 18:39:46 +0000 Subject: [PATCH 09/47] NIHVIVO-1291 fix to general Jena implementation isMemberOfClassProhibitedFromSearch --- .../cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java index 2ed582c95..0a011fc51 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java @@ -781,7 +781,7 @@ public class IndividualJena extends IndividualImpl implements Individual { if (stmt.getObject().isURIResource()) { String typeURI = ((Resource)stmt.getObject()).getURI(); if (pfs.isClassProhibited(typeURI)) { - return false; + return true; } } } From 31136651d858312d7e80afa5d4bace0e5449349d Mon Sep 17 00:00:00 2001 From: manolobevia Date: Mon, 13 Jun 2011 18:48:39 +0000 Subject: [PATCH 10/47] NIHVIVO-2280: Styled 'user account EDIT' page, and added breadcrumbs. --- .../freemarker/body/accounts/userAccounts-edit.ftl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl index b6d818f65..2d732c408 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl @@ -2,7 +2,7 @@ <#-- Template for editing a user account --> -

Edit account

+

> Edit account

<#if errorEmailIsEmpty??> <#assign errorMessage = "You must supply an email address." /> @@ -53,13 +53,13 @@
- + - + - +

Roles *

<#list roles as role> @@ -70,13 +70,13 @@ <#if !emailIsEnabled??> - +

Minimum of ${minimumLength} characters in length.

Leaving this blank means that the password will not be changed.

- +

Associate a profile with this account

@@ -98,7 +98,7 @@

- or Cancel + or Cancel

* required fields

From b9aa9140744d37ea525822069ddc9b8949798e23 Mon Sep 17 00:00:00 2001 From: manolobevia Date: Mon, 13 Jun 2011 19:58:58 +0000 Subject: [PATCH 11/47] NIHVIVO-2280: Styled 'my account' page. If changes are successful in this page, the feedback message has to be treated as a feedback not as error alert. Need to ask Jim to handle this in a different way. --- .../body/accounts/userAccounts-myAccount.ftl | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl index e00f13c41..943288f0b 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl @@ -2,7 +2,7 @@ <#-- Template for editing a user account --> -

Edit account

+

My account

<#if errorEmailIsEmpty??> <#assign errorMessage = "You must supply an email address." /> @@ -43,7 +43,6 @@ - <#if confirmChange??> <#assign confirmMessage = "Your changes have been saved." /> @@ -65,28 +64,27 @@
- + -

Note: if email changes, a confirmation email will be sent to the new email address entered above.

- +

Note: if email changes, a confirmation email will be sent to the new email address entered above.

+ - + - + <#if !externalAuth??> - + -

Minimum of ${minimumLength} characters in length.

-

Leaving this blank means that the password will not be changed.

+

Minimum of ${minimumLength} characters in length. Leaving this blank means that the password will not be changed.

- + - +

* required fields

From 9c9f7dfe570399b03a2f190d0f0d02e5554d9b23 Mon Sep 17 00:00:00 2001 From: manolobevia Date: Mon, 13 Jun 2011 21:41:29 +0000 Subject: [PATCH 12/47] NIHVIVO-2280: Styled 'reset password' page. --- .../accounts/userAccounts-resetPassword.ftl | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPassword.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPassword.ftl index d0f8e75a5..7208e325b 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPassword.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPassword.ftl @@ -4,6 +4,8 @@

Reset your Password

+

Please enter your new password for ${userAccount.emailAddress}

+ <#if errorPasswordIsEmpty??> <#assign errorMessage = "No password supplied." /> @@ -24,26 +26,22 @@
-
- Please enter your new password for ${userAccount.emailAddress} - -
- - + + + - - + + -

Minimum of ${minimumLength} characters in length.

+

Minimum of ${minimumLength} characters in length.

- - + + - +

-

* required fields

-
-
+

* required fields

+
${stylesheets.add('')} \ No newline at end of file From 2fcff042e6954d74fd9ea8908690dc3007c56fd3 Mon Sep 17 00:00:00 2001 From: ryounes Date: Tue, 14 Jun 2011 12:34:39 +0000 Subject: [PATCH 13/47] NIHVIVO-2693 Add Freemarker user-defined directive for email and integrate into email messaging framework. --- .../accounts/admin/UserAccountsEditPage.java | 2 +- .../admin/UserAccountsEditPageStrategy.java | 26 +++-- .../freemarker/FreemarkerHttpServlet.java | 13 ++- .../webapp/email/FreemarkerEmailMessage.java | 70 ++++++++++++ .../webapp/web/directives/EmailDirective.java | 100 ++++++++++++++++++ .../webapp/web/directives/UrlDirective.java | 14 ++- .../web/directives/WidgetDirective.java | 1 + .../userAccounts-passwordResetEmail-html.ftl | 2 +- .../userAccounts-resetPasswordEmail.ftl | 50 +++++++++ 9 files changed, 260 insertions(+), 18 deletions(-) create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java create mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java index c939dfe24..6151d7d32 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java @@ -200,7 +200,7 @@ public class UserAccountsEditPage extends UserAccountsPage { userAccountsDao.updateUserAccount(userAccount); - strategy.notifyUser(); + strategy.notifyUser(vreq); } public boolean wasPasswordEmailSent() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java index c174f8288..d06105c6b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java @@ -47,7 +47,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { protected abstract void setAdditionalProperties(UserAccount u); - protected abstract void notifyUser(); + protected abstract void notifyUser(VitroRequest vreq); protected abstract boolean wasPasswordEmailSent(); @@ -57,7 +57,8 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { private static class EmailStrategy extends UserAccountsEditPageStrategy { private static final String PARAMETER_RESET_PASSWORD = "resetPassword"; - + private static final String EMAIL_TEMPLATE = "userAccounts-resetPasswordEmail.ftl"; + public static final String RESET_PASSWORD_URL = "/accounts/resetPassword"; private boolean resetPassword; @@ -94,7 +95,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { } @Override - protected void notifyUser() { + protected void notifyUser(VitroRequest vreq) { if (!resetPassword) { return; } @@ -102,16 +103,21 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { Map body = new HashMap(); body.put("userAccount", page.getUpdatedAccount()); body.put("passwordLink", buildResetPasswordLink()); - body.put("subjectLine", "Reset password request"); + //body.put("subjectLine", "Reset password request"); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress()); - email.setSubject("Reset password request"); - email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl"); - email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl"); - email.setBodyMap(body); - email.send(); + + vreq.setAttribute("email", email); + + email.processTemplate(vreq, EMAIL_TEMPLATE, body); + + //email.setSubject("Reset password request"); + //email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl"); + //email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl"); + //email.setBodyMap(body); + //email.send(); sentEmail = true; } @@ -193,7 +199,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { } @Override - protected void notifyUser() { + protected void notifyUser(VitroRequest vreq) { // Do nothing. } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java index fed74cbe0..6371bc0e6 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java @@ -306,11 +306,18 @@ public class FreemarkerHttpServlet extends VitroHttpServlet { */ public static Map getDirectives() { Map map = new HashMap(); - map.put("dump", new freemarker.ext.dump.DumpDirective()); - map.put("dumpAll", new freemarker.ext.dump.DumpAllDirective()); - map.put("help", new freemarker.ext.dump.HelpDirective()); + map.putAll(getDirectivesForAllEnvironments()); map.put("url", new edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective()); map.put("widget", new edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective()); + + return map; + } + + public static Map getDirectivesForAllEnvironments() { + Map map = new HashMap(); + map.put("dump", new freemarker.ext.dump.DumpDirective()); + map.put("dumpAll", new freemarker.ext.dump.DumpAllDirective()); + map.put("help", new freemarker.ext.dump.HelpDirective()); return map; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java index 3bc9115cf..72fb702d5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java @@ -2,6 +2,8 @@ package edu.cornell.mannlib.vitro.webapp.email; +import java.io.IOException; +import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; @@ -27,9 +29,14 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException; +import freemarker.core.Environment; import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; /** * A framework that makes it simpler to send email messages with a body built @@ -146,6 +153,69 @@ public class FreemarkerEmailMessage { .unmodifiableMap(new HashMap(body)); } } + + public void processTemplate(VitroRequest vreq, String templateName, Map map) { + + vreq.setAttribute("email", this); + + map.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments()); + map.put("email", new edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective()); + + try { + Template template = config.getTemplate(templateName); + StringWriter writer = new StringWriter(); + Environment env = template.createProcessingEnvironment(map, writer); + env.setCustomAttribute("request", vreq); + env.process(); + } catch (TemplateException e) { + log.error(e, e); + } catch (IOException e) { + log.error(e, e); + } + } + + public void send(String subject, String html, String text) { + try { + MimeMessage msg = new MimeMessage(session); + msg.setReplyTo(new Address[] { replyToAddress }); + + if (fromAddress == null) { + msg.addFrom(new Address[] { replyToAddress }); + } else { + msg.addFrom(new Address[] { fromAddress }); + } + + for (Recipient recipient : recipients) { + msg.addRecipient(recipient.type, recipient.address); + } + + msg.setSubject(subject); + + if (html.isEmpty()) { + if (html.isEmpty()) { + log.error("Message has neither text body nor HTML body"); + } else { + msg.setContent(html, "text/html"); + } + } else { + if (html.isEmpty()) { + msg.setContent(text, "text/plain"); + } else { + MimeMultipart content = new MimeMultipart("alternative"); + addBodyPart(content, text, "text/plain"); + addBodyPart(content, html, "text/html"); + msg.setContent(content); + } + } + + msg.setSentDate(new Date()); + + Transport.send(msg); + + } catch (MessagingException e) { + log.error("Failed to send message.", e); + } + } public void send() { String textBody = figureMessageBody(textTemplateName); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java new file mode 100644 index 000000000..f3d75523b --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java @@ -0,0 +1,100 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.web.directives; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage; +import freemarker.core.Environment; +import freemarker.template.SimpleScalar; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; + +public class EmailDirective extends BaseTemplateDirectiveModel { + + private static final Log log = LogFactory.getLog(EmailDirective.class); + + @Override + public void execute(Environment env, Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + + Object o = params.get("subject"); + if (o == null) { + throw new TemplateModelException( + "The email directive requires a value for parameter 'subject'."); + } + if (! ( o instanceof SimpleScalar)) { + throw new TemplateModelException( + "The email directive requires a string value for parameter 'subject'."); + } + String subject = o.toString(); + + o = params.get("html"); + if (o == null) { + throw new TemplateModelException( + "The email directive requires a value for parameter 'html'."); + } + if (! ( o instanceof SimpleScalar)) { + throw new TemplateModelException( + "The email directive requires a string value for parameter 'html'."); + } + String html = o.toString(); + + o = params.get("text"); + if (o == null) { + throw new TemplateModelException( + "The email directive requires a value for parameter 'text'."); + } + if (! ( o instanceof SimpleScalar)) { + throw new TemplateModelException( + "The email directive requires a string value for parameter 'text'."); + } + String text = o.toString(); + + HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request"); + + o = (FreemarkerEmailMessage) request.getAttribute("email"); + if ( o == null) { + throw new TemplateModelException( + "No email object found in the request."); + } + if ( ! (o instanceof FreemarkerEmailMessage)) { + throw new TemplateModelException( + "Invalid value for request email attribute"); + } + FreemarkerEmailMessage email = (FreemarkerEmailMessage) o; + email.send(subject, html, text); + + } + + @Override + public Map help(String name) { + Map map = new LinkedHashMap(); + + map.put("effect", "Create an email message from the parameters set in the invoking template."); + + Map params = new HashMap(); + params.put("subject", "email subject"); + params.put("html", "HTML version of email message"); + params.put("text", "Plain text version of email message"); + map.put("parameters", params); + + List examples = new ArrayList(); + examples.add("<email subject=\"Password reset confirmation\" html=html text=text>"); + map.put("examples", examples); + + return map; + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/UrlDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/UrlDirective.java index 85a59a7cd..9edf3ff85 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/UrlDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/UrlDirective.java @@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import freemarker.core.Environment; +import freemarker.template.SimpleScalar; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; @@ -44,12 +45,19 @@ public class UrlDirective extends BaseTemplateDirectiveModel { "The url directive doesn't allow nested content."); } - String path = params.get("path").toString(); - if (path == null) { + Object o = params.get("path"); + if (o == null) { throw new TemplateModelException( "The url directive requires a value for parameter 'path'."); } + if (! ( o instanceof SimpleScalar)) { + throw new TemplateModelException( + "The url directive requires a string value for parameter 'path'."); + } + + String path = o.toString(); + if (!path.startsWith("/")) { throw new TemplateModelException( "The url directive requires that the value of parameter 'path' is an absolute path starting with '/'."); @@ -60,6 +68,7 @@ public class UrlDirective extends BaseTemplateDirectiveModel { out.write(url); } + @Override public Map help(String name) { Map map = new LinkedHashMap(); @@ -77,6 +86,5 @@ public class UrlDirective extends BaseTemplateDirectiveModel { return map; } - } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java index 654f5cecc..dff8eae6c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/WidgetDirective.java @@ -94,6 +94,7 @@ public class WidgetDirective extends BaseTemplateDirectiveModel { } + @Override public Map help(String name) { Map map = new LinkedHashMap(); diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-html.ftl index 5212fbebb..49c4eb531 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-html.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-html.ftl @@ -1,6 +1,6 @@ <#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> -<#-- Confirmation that an password has been reset. --> +<#-- Confirmation that a password has been reset. --> diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl new file mode 100644 index 000000000..ca1e84abc --- /dev/null +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl @@ -0,0 +1,50 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +<#-- Confirmation email for user account password reset --> + +<#assign subject = "Reset password request" /> + +<#assign html> + + + ${subject} + + +

+ ${userAccount.firstName} ${userAccount.lastName} +

+ +

+ Password successfully changed. +

+ +

+ Your new password associated with ${userAccount.emailAddress} has been changed. +

+ +

+ Thank you. +

+ + + + +<#assign text> +${userAccount.firstName} ${userAccount.lastName} + +We received a request to reset the password for your account +(${userAccount.emailAddress}). +Please follow the instructions below to proceed with your password reset. + +If you did not request this new account you can safely ignore this email. +This request will expire if not acted upon for 30 days. + +Paste the link below into your browser's address bar to reset your password +using our secure server. + +${passwordLink} + +Thank you! + + +<@email subject=subject html=html text=text /> \ No newline at end of file From f5c44298e1232802da1fc0f05d6a19d93bbf409f Mon Sep 17 00:00:00 2001 From: ryounes Date: Tue, 14 Jun 2011 13:26:52 +0000 Subject: [PATCH 14/47] NIHVIVO-2693 Freemarker email messaging code refactoring --- .../accounts/admin/UserAccountsEditPage.java | 2 +- .../admin/UserAccountsEditPageStrategy.java | 25 ++++++++--------- .../freemarker/FreemarkerHttpServlet.java | 3 --- .../webapp/email/FreemarkerEmailMessage.java | 18 ++++++++----- .../webapp/web/directives/EmailDirective.java | 4 +-- .../userAccounts-resetPasswordEmail.ftl | 27 +++++++++++++------ 6 files changed, 46 insertions(+), 33 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java index 6151d7d32..c939dfe24 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java @@ -200,7 +200,7 @@ public class UserAccountsEditPage extends UserAccountsPage { userAccountsDao.updateUserAccount(userAccount); - strategy.notifyUser(vreq); + strategy.notifyUser(); } public boolean wasPasswordEmailSent() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java index d06105c6b..1c1a3f383 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java @@ -9,8 +9,8 @@ import java.net.URL; import java.util.HashMap; import java.util.Map; +import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; -import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage; import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator; @@ -47,7 +47,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { protected abstract void setAdditionalProperties(UserAccount u); - protected abstract void notifyUser(VitroRequest vreq); + protected abstract void notifyUser(); protected abstract boolean wasPasswordEmailSent(); @@ -95,7 +95,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { } @Override - protected void notifyUser(VitroRequest vreq) { + protected void notifyUser() { if (!resetPassword) { return; } @@ -103,24 +103,25 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { Map body = new HashMap(); body.put("userAccount", page.getUpdatedAccount()); body.put("passwordLink", buildResetPasswordLink()); - //body.put("subjectLine", "Reset password request"); + body.put("siteName", getSiteName()); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress()); + email.setTemplate(EMAIL_TEMPLATE); + email.setBodyMap(body); vreq.setAttribute("email", email); - email.processTemplate(vreq, EMAIL_TEMPLATE, body); - - //email.setSubject("Reset password request"); - //email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl"); - //email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl"); - //email.setBodyMap(body); - //email.send(); + email.processTemplate(vreq); sentEmail = true; } + + private String getSiteName() { + ApplicationBean appBean = vreq.getAppBean(); + return appBean.getApplicationName(); + } private String buildResetPasswordLink() { try { @@ -199,7 +200,7 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { } @Override - protected void notifyUser(VitroRequest vreq) { + protected void notifyUser() { // Do nothing. } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java index 6371bc0e6..f0430dc64 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java @@ -337,9 +337,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet { Map map = new HashMap(); ApplicationBean appBean = vreq.getAppBean(); - // Ideally, templates wouldn't need portal id. Currently used as a hidden input value - // in the site search box, so needed for now. - String siteName = appBean.getApplicationName(); map.put("siteName", siteName); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java index 72fb702d5..53e0b0c8e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java @@ -61,6 +61,7 @@ public class FreemarkerEmailMessage { private InternetAddress fromAddress = null; private String subject = ""; + private String templateName; private String htmlTemplateName; private String textTemplateName; private Map bodyMap = Collections.emptyMap(); @@ -144,27 +145,30 @@ public class FreemarkerEmailMessage { public void setTextTemplate(String templateName) { this.textTemplateName = nonNull(templateName, ""); } + + public void setTemplate(String templateName) { + this.templateName = nonNull(templateName, ""); + } public void setBodyMap(Map body) { if (body == null) { this.bodyMap = Collections.emptyMap(); } else { - this.bodyMap = Collections - .unmodifiableMap(new HashMap(body)); + this.bodyMap = new HashMap(body); } } - public void processTemplate(VitroRequest vreq, String templateName, Map map) { + public void processTemplate(VitroRequest vreq) { - vreq.setAttribute("email", this); + vreq.setAttribute("emailMessage", this); - map.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments()); - map.put("email", new edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective()); + bodyMap.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments()); + bodyMap.put("email", new edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective()); try { Template template = config.getTemplate(templateName); StringWriter writer = new StringWriter(); - Environment env = template.createProcessingEnvironment(map, writer); + Environment env = template.createProcessingEnvironment(bodyMap, writer); env.setCustomAttribute("request", vreq); env.process(); } catch (TemplateException e) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java index f3d75523b..515acf72e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java @@ -65,10 +65,10 @@ public class EmailDirective extends BaseTemplateDirectiveModel { HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request"); - o = (FreemarkerEmailMessage) request.getAttribute("email"); + o = (FreemarkerEmailMessage) request.getAttribute("emailMessage"); if ( o == null) { throw new TemplateModelException( - "No email object found in the request."); + "No email message object found in the request."); } if ( ! (o instanceof FreemarkerEmailMessage)) { throw new TemplateModelException( diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl index ca1e84abc..d6fcc59a2 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail.ftl @@ -2,7 +2,7 @@ <#-- Confirmation email for user account password reset --> -<#assign subject = "Reset password request" /> +<#assign subject = "${siteName} reset password request" /> <#assign html> @@ -11,33 +11,44 @@

- ${userAccount.firstName} ${userAccount.lastName} + Dear ${userAccount.firstName} ${userAccount.lastName}:

- Password successfully changed. + We have received a request to reset the password for your ${siteName} account (${userAccount.emailAddress}).

- Your new password associated with ${userAccount.emailAddress} has been changed. + Please follow the instructions below to proceed with your password reset.

- Thank you. + If you did not request this new account you can safely ignore this email. + This request will expire if not acted upon within 30 days.

+ +

+ Click on the link below or paste it into your browser's address bar to reset your password + using our secure server. +

+ +

${passwordLink}

+ +

Thank you!

<#assign text> -${userAccount.firstName} ${userAccount.lastName} +Dear ${userAccount.firstName} ${userAccount.lastName}: -We received a request to reset the password for your account +We have received a request to reset the password for your ${siteName} account (${userAccount.emailAddress}). + Please follow the instructions below to proceed with your password reset. If you did not request this new account you can safely ignore this email. -This request will expire if not acted upon for 30 days. +This request will expire if not acted upon within 30 days. Paste the link below into your browser's address bar to reset your password using our secure server. From cedd095a077fe473301a22d9ba32205c0548b019 Mon Sep 17 00:00:00 2001 From: manolobevia Date: Tue, 14 Jun 2011 14:53:22 +0000 Subject: [PATCH 15/47] NIHVIVO-2280: Removed asterisk for New password and Confirm new password field. Also changed wording for Confirm initial password to Confirm new password. --- .../freemarker/body/accounts/userAccounts-myAccount.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl index 943288f0b..3067e43f6 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-myAccount.ftl @@ -75,12 +75,12 @@ <#if !externalAuth??> - +

Minimum of ${minimumLength} characters in length. Leaving this blank means that the password will not be changed.

- + From 4282da5ef2d6e0d69fdf1c0df49a60f017751794 Mon Sep 17 00:00:00 2001 From: j2blake Date: Tue, 14 Jun 2011 17:11:26 +0000 Subject: [PATCH 16/47] NIHVIVO-2696 External user gets an account on first login. --- .../UserAccountsFirstTimeExternalPage.java | 72 ++++++++++++++----- .../user/UserAccountsUserController.java | 33 +++++++-- .../authenticate/Authenticator.java | 11 --- .../authenticate/BasicAuthenticator.java | 19 +---- .../authenticate/LoginExternalAuthReturn.java | 32 +++------ .../authenticate/AuthenticatorStub.java | 6 -- .../userAccounts-firstTimeExternal.ftl | 1 + 7 files changed, 94 insertions(+), 80 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java index f180d23c9..7b1d00572 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPage.java @@ -9,6 +9,8 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import org.apache.commons.lang.StringUtils; + import edu.cornell.mannlib.vitro.webapp.auth.permissions.PermissionSetsLoader; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount.Status; @@ -22,13 +24,14 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem * Handle the first-time login of an Externally Authenticated user who has no * UserAccount - let's create one! * - * If they get here from the login, there should an externalAuthId waiting in - * the session. Otherwise, they should get here by submitting the form, which - * will have the externalAuthId as a hidden field. + * If they get here from the login, there should be an ExternalLoginInfo waiting + * in the session. Otherwise, they should get here by submitting the form, which + * will have the info in hidden fields. */ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage { private static final String PARAMETER_SUBMIT = "submit"; private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId"; + private static final String PARAMETER_AFTER_LOGIN_URL = "afterLoginUrl"; private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress"; private static final String PARAMETER_FIRST_NAME = "firstName"; private static final String PARAMETER_LAST_NAME = "lastName"; @@ -41,23 +44,25 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage { private static final String TEMPLATE_NAME = "userAccounts-firstTimeExternal.ftl"; - private static final String ATTRIBUTE_EXTERNAL_AUTH_ID = UserAccountsFirstTimeExternalPage.class + private static final String ATTRIBUTE_EXTERNAL_LOGIN_INFO = UserAccountsFirstTimeExternalPage.class .getName(); /** - * Let some other request set the External Auth ID before redirecting to - * here. + * Let some other request set the External Auth ID and the afterLogin URL + * before redirecting to here. */ - public static void setExternalAuthId(HttpServletRequest req, - String externalAuthId) { - req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID, - externalAuthId); + public static void setExternalLoginInfo(HttpServletRequest req, + String externalAuthId, String afterLoginUrl) { + req.getSession().setAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO, + new ExternalLoginInfo(externalAuthId, afterLoginUrl)); } private final UserAccountsFirstTimeExternalPageStrategy strategy; - private boolean submit = false; private String externalAuthId = ""; + private String afterLoginUrl = ""; + + private boolean submit = false; private String emailAddress = ""; private String firstName = ""; private String lastName = ""; @@ -71,7 +76,7 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage { this.strategy = UserAccountsFirstTimeExternalPageStrategy.getInstance( vreq, this, isEmailEnabled()); - checkSessionForExternalAuthId(); + checkSessionForExternalLoginInfo(); if (externalAuthId.isEmpty()) { parseRequestParameters(); } @@ -83,20 +88,26 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage { } } - private void checkSessionForExternalAuthId() { + private void checkSessionForExternalLoginInfo() { HttpSession session = vreq.getSession(); - Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID); - session.removeAttribute(ATTRIBUTE_EXTERNAL_AUTH_ID); + Object o = session.getAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO); + session.removeAttribute(ATTRIBUTE_EXTERNAL_LOGIN_INFO); - if (o instanceof String) { - externalAuthId = (String) o; + if (o instanceof ExternalLoginInfo) { + externalAuthId = ((ExternalLoginInfo) o).externalAuthId; + afterLoginUrl = ((ExternalLoginInfo) o).afterLoginUrl; + if (afterLoginUrl == null) { + afterLoginUrl = ""; + } } } private void parseRequestParameters() { - submit = isFlagOnRequest(PARAMETER_SUBMIT); externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, ""); + afterLoginUrl = getStringParameter(PARAMETER_AFTER_LOGIN_URL, ""); + + submit = isFlagOnRequest(PARAMETER_SUBMIT); emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, ""); firstName = getStringParameter(PARAMETER_FIRST_NAME, ""); lastName = getStringParameter(PARAMETER_LAST_NAME, ""); @@ -156,10 +167,12 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage { public final ResponseValues showPage() { Map body = new HashMap(); + body.put("externalAuthId", externalAuthId); + body.put("afterLoginUrl", afterLoginUrl); + body.put("emailAddress", emailAddress); body.put("firstName", firstName); body.put("lastName", lastName); - body.put("externalAuthId", externalAuthId); body.put("formUrls", buildUrlsMap()); if (!errorCode.isEmpty()) { @@ -191,4 +204,25 @@ public class UserAccountsFirstTimeExternalPage extends UserAccountsPage { return u; } + /** + * If the afterLoginUrl is missing, go to the home page. If it is relative, + * make sure it doesn't start with the cotext path. + */ + public String getAfterLoginUrl() { + if (StringUtils.isEmpty(afterLoginUrl)) { + return null; + } + return afterLoginUrl; + } + + private static class ExternalLoginInfo { + final String externalAuthId; + final String afterLoginUrl; + + public ExternalLoginInfo(String externalAuthId, String afterLoginUrl) { + this.externalAuthId = externalAuthId; + this.afterLoginUrl = afterLoginUrl; + } + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java index 322dd6c2b..3dafd87f9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java @@ -4,10 +4,10 @@ package edu.cornell.mannlib.vitro.webapp.controller.accounts.user; import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.EXTERNAL; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOwnAccount; import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage; @@ -115,9 +115,7 @@ public class UserAccountsUserController extends FreemarkerHttpServlet { UserAccount userAccount = page.createAccount(); Authenticator auth = Authenticator.getInstance(vreq); auth.recordLoginAgainstUserAccount(userAccount, EXTERNAL); - LoginProcessBean.removeBean(vreq); - - return showLoginRedirection(vreq); + return showLoginRedirection(vreq, page.getAfterLoginUrl()); } else { return page.showPage(); } @@ -132,10 +130,31 @@ public class UserAccountsUserController extends FreemarkerHttpServlet { return new RedirectResponseValues("/"); } - private ResponseValues showLoginRedirection(VitroRequest vreq) { - LoginRedirector lr = new LoginRedirector(vreq, null); + private ResponseValues showLoginRedirection(VitroRequest vreq, + String afterLoginUrl) { + LoginRedirector lr = new LoginRedirector(vreq, afterLoginUrl); DisplayMessage.setMessage(vreq, lr.assembleWelcomeMessage()); String uri = lr.getRedirectionUriForLoggedInUser(); - return new RedirectResponseValues(uri); + return new RedirectResponseValues(stripContextPath(vreq, uri)); + } + + /** + * TODO The LoginRedirector gives a URI that includes the context path. But + * the RedirectResponseValues wants a URI that does not include the context + * path. + * + * Bridge the gap. + */ + private String stripContextPath(VitroRequest vreq, String uri) { + if ((uri == null) || uri.isEmpty() || uri.equals(vreq.getContextPath())) { + return "/"; + } + if (uri.contains("://")) { + return uri; + } + if (uri.startsWith(vreq.getContextPath() + '/')) { + return uri.substring(vreq.getContextPath().length()); + } + return uri; } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java index cddad2bdc..45b676164 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java @@ -105,17 +105,6 @@ public abstract class Authenticator { public abstract void recordLoginAgainstUserAccount(UserAccount userAccount, AuthenticationSource authSource); - /** - *
-	 * Record that the user has logged in but with only external authentication 
-	 * info, so no internal user account.
-	 * - this involves everything except updating the user record.
-	 * 
- * - * TODO JB This goes away. - */ - public abstract void recordLoginWithoutUserAccount(String individualUri); - /** *
 	 * Record that the current user has logged out: - notify other users of the
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java
index 2135f007f..f84bf041b 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java
@@ -3,7 +3,6 @@
 package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -123,24 +122,12 @@ public class BasicAuthenticator extends Authenticator {
 		}
 
 		recordLoginOnUserRecord(userAccount);
-		recordLoginWithOrWithoutUserAccount(userAccount.getUri(), authSource);
-	}
 
-	// TODO JB This goes away.
-	@Override
-	public void recordLoginWithoutUserAccount(String individualUri) {
-		recordLoginWithOrWithoutUserAccount(individualUri,
-				AuthenticationSource.EXTERNAL);
-	}
-
-	/** This much is in common on login, whether or not you have a user account. */
-	private void recordLoginWithOrWithoutUserAccount(String userUri,
-			AuthenticationSource authSource) {
 		HttpSession session = request.getSession();
-		createLoginStatusBean(userUri, authSource, session);
+		createLoginStatusBean(userAccount.getUri(), authSource, session);
 		setSessionTimeoutLimit(session);
-		recordInUserSessionMap(userUri, session);
-		notifyOtherUsers(userUri, session);
+		recordInUserSessionMap(userAccount.getUri(), session);
+		notifyOtherUsers(userAccount.getUri(), session);
 	}
 
 	/**
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java
index d970db6cd..ce008c64e 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthReturn.java
@@ -5,7 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.controller.authenticate;
 import static edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginExternalAuthSetup.ATTRIBUTE_REFERRER;
 
 import java.io.IOException;
-import java.util.List;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -16,6 +15,8 @@ import org.apache.commons.logging.LogFactory;
 
 import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource;
 import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
+import edu.cornell.mannlib.vitro.webapp.controller.accounts.user.UserAccountsFirstTimeExternalPage;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
 import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
 
 /**
@@ -57,37 +58,26 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
 					MESSAGE_LOGIN_FAILED);
 			return;
 		}
-		
+
 		String afterLoginUrl = LoginProcessBean.getBean(req).getAfterLoginUrl();
 		removeLoginProcessArtifacts(req);
 
 		UserAccount userAccount = getAuthenticator(req)
 				.getAccountForExternalAuth(externalAuthId);
-		if (userAccount != null) {
+		if (userAccount == null) {
+			log.debug("Creating new account for " + externalAuthId
+					+ ", return to '" + afterLoginUrl + "'");
+			UserAccountsFirstTimeExternalPage.setExternalLoginInfo(req,
+					externalAuthId, afterLoginUrl);
+			resp.sendRedirect(UrlBuilder.getUrl("/accounts/firstTimeExternal"));
+			return;
+		} else {
 			log.debug("Logging in as " + userAccount.getUri());
 			getAuthenticator(req).recordLoginAgainstUserAccount(userAccount,
 					AuthenticationSource.EXTERNAL);
 			new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp);
 			return;
 		}
-
-		List associatedUris = getAuthenticator(req)
-				.getAssociatedIndividualUris(userAccount);
-		// TODO JB - this case should lead to creating a new account.
-		if (!associatedUris.isEmpty()) {
-			log.debug("Recognize '" + externalAuthId + "' as self-editor for "
-					+ associatedUris);
-			String uri = associatedUris.get(0);
-
-			getAuthenticator(req).recordLoginWithoutUserAccount(uri);
-			new LoginRedirector(req, afterLoginUrl).redirectLoggedInUser(resp);
-			return;
-		}
-
-		log.debug("User is not recognized: " + externalAuthId);
-		removeLoginProcessArtifacts(req);
-		new LoginRedirector(req, afterLoginUrl).redirectUnrecognizedExternalUser(resp,
-				externalAuthId);
 	}
 
 	private void removeLoginProcessArtifacts(HttpServletRequest req) {
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java
index 6171387f9..3dd4fabd0 100644
--- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java
@@ -182,10 +182,4 @@ public class AuthenticatorStub extends Authenticator {
 				"AuthenticatorStub.accountRequiresEditing() not implemented.");
 	}
 
-	@Override
-	public void recordLoginWithoutUserAccount(String individualUri) {
-		throw new RuntimeException(
-				"AuthenticatorStub.recordLoginWithoutUserAccount() not implemented.");
-	}
-
 }
diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl
index 1b6b78791..8367ca164 100644
--- a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl
+++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl
@@ -39,6 +39,7 @@
 
         
+ From 558bcfb13f42987d64dd2451aa41986408670c29 Mon Sep 17 00:00:00 2001 From: j2blake Date: Tue, 14 Jun 2011 17:16:37 +0000 Subject: [PATCH 17/47] Expose the user's first name for use in the Identity template. --- .../mannlib/vitro/webapp/web/templatemodels/User.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java index e533847e5..9f1eef762 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java @@ -41,6 +41,14 @@ public class User extends BaseTemplateModel { return firstName + " " + lastName; } + public String getFirstName() { + if (currentUser == null) { + return ""; + } else { + return currentUser.getFirstName(); + } + } + public boolean getHasSiteAdminAccess() { return PolicyHelper.isAuthorizedForActions(vreq, SiteAdminController.REQUIRED_ACTIONS); } From 367d0bf9b4192d3df6fd3a4216efda432266d955 Mon Sep 17 00:00:00 2001 From: manolobevia Date: Tue, 14 Jun 2011 18:49:03 +0000 Subject: [PATCH 18/47] NIHVIVO-2280: Changed note to "Instructions for resetting the password will be emailed to the address entered above. The password will not be reset until the user follows the link provided in this email." --- .../freemarker/body/accounts/userAccounts-edit.ftl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl index 2d732c408..0d9e30718 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl @@ -92,9 +92,9 @@ <#if emailIsEnabled??>

- Note: A confirmation email with instructions for resetting a password - will be sent to the address entered above. - The password will not be reset until the user follows the link provided in this email. + Note: Instructions for resetting the password will + be emailed to the address entered above. The password will not + be reset until the user follows the link provided in this email.

From 4f3e29890f2f6470f97f479015acf8998135de6d Mon Sep 17 00:00:00 2001 From: ryounes Date: Tue, 14 Jun 2011 19:36:22 +0000 Subject: [PATCH 19/47] NIHVIVO-2709 Fix code error to prevent error during variable dump --- .../webapp/web/templatemodels/VClassTemplateModel.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassTemplateModel.java index 059d70d6a..676dbfe02 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/VClassTemplateModel.java @@ -6,6 +6,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route; @@ -36,7 +37,8 @@ public class VClassTemplateModel extends BaseTemplateModel { return vclass.getEntityCount(); } - public VClassGroupTemplateModel getGroup(){ - return new VClassGroupTemplateModel(vclass.getGroup()); + public VClassGroupTemplateModel getGroup() { + VClassGroup group = vclass.getGroup(); + return (group == null) ? null : new VClassGroupTemplateModel(vclass.getGroup()); } } From edfd1798efe56fe15cf14dba079587272eca7b9f Mon Sep 17 00:00:00 2001 From: j2blake Date: Tue, 14 Jun 2011 20:00:33 +0000 Subject: [PATCH 20/47] Expose the user's last name for use in the Identity template. --- .../mannlib/vitro/webapp/web/templatemodels/User.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java index 9f1eef762..5caeb8f0a 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java @@ -49,6 +49,14 @@ public class User extends BaseTemplateModel { } } + public String getLastName() { + if (currentUser == null) { + return ""; + } else { + return currentUser.getLastName(); + } + } + public boolean getHasSiteAdminAccess() { return PolicyHelper.isAuthorizedForActions(vreq, SiteAdminController.REQUIRED_ACTIONS); } From ef3affb349ebfb1210adcd5339d7c1675d926749 Mon Sep 17 00:00:00 2001 From: j2blake Date: Tue, 14 Jun 2011 20:12:57 +0000 Subject: [PATCH 21/47] Write a warning to the log if a root user already exists with an email address that is different from the one in the deploy.properties --- .../webapp/auth/policy/RootUserPolicy.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java index 85e069d12..aeb67bd5c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java @@ -75,6 +75,8 @@ public class RootUserPolicy implements PolicyIface { UserAccountsDao uaDao = getUserAccountsDao(ctx); OntModel userAccountsModel = getUserAccountsModel(ctx); + checkForWrongRootUser(ctx, uaDao); + if (!rootUserExists(uaDao)) { createRootUser(ctx, uaDao, userAccountsModel); } @@ -103,13 +105,34 @@ public class RootUserPolicy implements PolicyIface { .getUserAccountsModel(); } + private void checkForWrongRootUser(ServletContext ctx, + UserAccountsDao uaDao) { + UserAccount root = getRootUser(uaDao); + if (root == null) { + return; + } + String actualRootEmail = root.getEmailAddress(); + + String configRootEmail = ConfigurationProperties.getBean(ctx) + .getProperty(PROPERTY_ROOT_USER_EMAIL); + if (actualRootEmail.equals(configRootEmail)) { + return; + } + + log.warn("Root user '" + actualRootEmail + "' already exists."); + } + private boolean rootUserExists(UserAccountsDao uaDao) { + return (getRootUser(uaDao) != null); + } + + private UserAccount getRootUser(UserAccountsDao uaDao) { for (UserAccount ua : uaDao.getAllUserAccounts()) { if (uaDao.isRootUser(ua)) { - return true; + return ua; } } - return false; + return null; } /** From 6f58b677cbd9ac340ae5c59a9531ab7f3817f757 Mon Sep 17 00:00:00 2001 From: brianjlowe Date: Tue, 14 Jun 2011 21:14:49 +0000 Subject: [PATCH 22/47] NIHVIVO-2708 removed unnecessary iteration in getMainImageUri() --- .../vitro/webapp/dao/jena/IndividualSDB.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java index 95216e798..32c6ee464 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java @@ -456,13 +456,13 @@ public class IndividualSDB extends IndividualImpl implements Individual { if (this.mainImageUri != NOT_INITIALIZED) { return mainImageUri; } else { - for (ObjectPropertyStatement stmt : getObjectPropertyStatements()) { - if (stmt.getPropertyURI() - .equals(VitroVocabulary.IND_MAIN_IMAGE)) { - mainImageUri = stmt.getObjectURI(); - return mainImageUri; - } - } + List mainImgStmts = + getObjectPropertyStatements(VitroVocabulary.IND_MAIN_IMAGE); + if (mainImgStmts != null && mainImgStmts.size() > 0) { + // arbitrarily return the first value in the list + mainImageUri = mainImgStmts.get(0).getObjectURI(); + return mainImageUri; + } return null; } } From e970abcae946aeb81da42b5e73980dcfa054735a Mon Sep 17 00:00:00 2001 From: tworrall Date: Wed, 15 Jun 2011 14:39:22 +0000 Subject: [PATCH 23/47] NIHVIVO-2710: improved type facet on the search results page --- webapp/web/css/vitro.css | 38 +++++++++++++++++++ .../body/search/search-pagedResults.ftl | 12 ++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/webapp/web/css/vitro.css b/webapp/web/css/vitro.css index 184c7f688..8452671b3 100644 --- a/webapp/web/css/vitro.css +++ b/webapp/web/css/vitro.css @@ -74,3 +74,41 @@ height:620px; overflow:visible; } +/* <------ SEARCH RESULTS PAGE*/ +.searchTOC { + margin-bottom: 1.5em; + float:right; + margin-right:35px; + margin-left:45px; + width:182px; + text-align:center; +/* border: 1px solid #dde4e3;*/ + padding-top:4px; + color: #fff; + background: #5e6363; +} +.searchTOC span { + color: #fff; +} +.searchTOC ul { + width: 160px; + border: 1px solid #dde4e3; + background: #f1f2ee; + padding: 0 10px 0px 10px; + margin-top: 4px; + text-align: left; +} +.searchTOC ul li { + display: block; + border-bottom: 1px solid #dde4e3; + font-size: 14px; + height: 35px; + line-height: 35px; +} +.searchTOC ul li:last-child { + border-bottom: none +} +.searchTOC ul a { + display: block; + padding-left: 15px; +} \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl b/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl index bf4600af4..8030d496b 100644 --- a/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl +++ b/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl @@ -13,19 +13,23 @@ <#-- Refinement links --> <#if classGroupLinks?has_content>
- Show only results of this type: + Display only +
<#if classLinks?has_content>
- Show only results of this subtype: + Limit ${classGroupName} to +
From 3c1cbff0e08a660992f197e73621404616dbd731 Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 15 Jun 2011 14:50:44 +0000 Subject: [PATCH 24/47] Change the way that Login name is configured. --- .../vitro/webapp/web/templatemodels/User.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java index 5caeb8f0a..5b9a217d7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java @@ -32,13 +32,11 @@ public class User extends BaseTemplateModel { return ""; } - String firstName = currentUser.getFirstName(); - String lastName = currentUser.getLastName(); - if (firstName.isEmpty() && lastName.isEmpty()) { - return currentUser.getEmailAddress(); - } - - return firstName + " " + lastName; + if (currentUser.getFirstName().isEmpty()) { + return currentUser.getEmailAddress(); + } + + return currentUser.getFirstName(); } public String getFirstName() { From c94ad4511b6d0a1b02bbbb8feadcbd6460c242b7 Mon Sep 17 00:00:00 2001 From: ryounes Date: Wed, 15 Jun 2011 16:24:48 +0000 Subject: [PATCH 25/47] NIHVIVO-2693 Add option to set default subject, html, and text attributes of email object in case template doesn't supply them. --- .../admin/UserAccountsEditPageStrategy.java | 27 +++++-- .../webapp/email/FreemarkerEmailMessage.java | 68 +++++++++++----- .../webapp/web/directives/EmailDirective.java | 77 ++++++++----------- 3 files changed, 106 insertions(+), 66 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java index 1c1a3f383..3ca3c739c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java @@ -103,13 +103,18 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { Map body = new HashMap(); body.put("userAccount", page.getUpdatedAccount()); body.put("passwordLink", buildResetPasswordLink()); - body.put("siteName", getSiteName()); + + String siteName = getSiteName(); + body.put("siteName", siteName); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress()); email.setTemplate(EMAIL_TEMPLATE); - email.setBodyMap(body); + email.setBodyMap(body); + email.setDefaultSubject(getDefaultSubject(siteName)); + email.setDefaultHtml(getDefaultHtml()); + email.setDefaultText(getDefaultText()); vreq.setAttribute("email", email); @@ -117,10 +122,22 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { sentEmail = true; } - + private String getSiteName() { - ApplicationBean appBean = vreq.getAppBean(); - return appBean.getApplicationName(); + ApplicationBean appBean = vreq.getAppBean(); + return appBean.getApplicationName(); + } + + private String getDefaultSubject(String siteName) { + return siteName + " reset password request"; + } + + private String getDefaultHtml() { + return ""; + } + + private String getDefaultText() { + return "Default text for user accounts edit page"; } private String buildResetPasswordLink() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java index 53e0b0c8e..5e2ec8597 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java @@ -26,6 +26,7 @@ import javax.mail.internet.MimeMultipart; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -61,10 +62,15 @@ public class FreemarkerEmailMessage { private InternetAddress fromAddress = null; private String subject = ""; + private String defaultSubject = ""; + private String defaultHtml = ""; + private String defaultText = ""; private String templateName; - private String htmlTemplateName; - private String textTemplateName; private Map bodyMap = Collections.emptyMap(); + + // TO BE REMOVED + private String htmlTemplateName; + private String textTemplateName; /** * Package access - should only be created by the factory. @@ -133,22 +139,36 @@ public class FreemarkerEmailMessage { return; } } - - public void setSubject(String subject) { - this.subject = nonNull(subject, ""); - } - + + // TO BE REMOVED public void setHtmlTemplate(String templateName) { this.htmlTemplateName = nonNull(templateName, ""); } + // TO BE REMOVED public void setTextTemplate(String templateName) { this.textTemplateName = nonNull(templateName, ""); } + + public void setSubject(String subject) { + this.subject = nonNull(subject, ""); + } public void setTemplate(String templateName) { this.templateName = nonNull(templateName, ""); } + + public void setDefaultSubject(String defaultSubject) { + this.defaultSubject = nonNull(defaultSubject, ""); + } + + public void setDefaultHtml(String defaultHtml) { + this.defaultHtml = nonNull(defaultHtml, ""); + } + + public void setDefaultText(String defaultText) { + this.defaultText = nonNull(defaultText, ""); + } public void setBodyMap(Map body) { if (body == null) { @@ -192,24 +212,36 @@ public class FreemarkerEmailMessage { for (Recipient recipient : recipients) { msg.addRecipient(recipient.type, recipient.address); } - + + if (subject == null) { + log.debug("No email subject specified in template. Using default subject."); + subject = defaultSubject; + } msg.setSubject(subject); - if (html.isEmpty()) { - if (html.isEmpty()) { + if (html == null) { + log.debug("No html email specified in template. Using default html."); + html = defaultHtml; + } + + if (text == null) { + log.debug("No plain text email specified in template. Using default html."); + text = defaultText; + } + + if (StringUtils.isEmpty(text)) { + if (StringUtils.isEmpty(html)) { log.error("Message has neither text body nor HTML body"); } else { msg.setContent(html, "text/html"); } + } else if (StringUtils.isEmpty(html)) { + msg.setContent(text, "text/plain"); } else { - if (html.isEmpty()) { - msg.setContent(text, "text/plain"); - } else { - MimeMultipart content = new MimeMultipart("alternative"); - addBodyPart(content, text, "text/plain"); - addBodyPart(content, html, "text/html"); - msg.setContent(content); - } + MimeMultipart content = new MimeMultipart("alternative"); + addBodyPart(content, text, "text/plain"); + addBodyPart(content, html, "text/html"); + msg.setContent(content); } msg.setSentDate(new Date()); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java index 515acf72e..e492d40a7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java @@ -29,54 +29,43 @@ public class EmailDirective extends BaseTemplateDirectiveModel { @Override public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException { - - Object o = params.get("subject"); - if (o == null) { - throw new TemplateModelException( - "The email directive requires a value for parameter 'subject'."); - } - if (! ( o instanceof SimpleScalar)) { - throw new TemplateModelException( - "The email directive requires a string value for parameter 'subject'."); - } - String subject = o.toString(); - - o = params.get("html"); - if (o == null) { - throw new TemplateModelException( - "The email directive requires a value for parameter 'html'."); - } - if (! ( o instanceof SimpleScalar)) { - throw new TemplateModelException( - "The email directive requires a string value for parameter 'html'."); - } - String html = o.toString(); - - o = params.get("text"); - if (o == null) { - throw new TemplateModelException( - "The email directive requires a value for parameter 'text'."); - } - if (! ( o instanceof SimpleScalar)) { - throw new TemplateModelException( - "The email directive requires a string value for parameter 'text'."); - } - String text = o.toString(); HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request"); - - o = (FreemarkerEmailMessage) request.getAttribute("emailMessage"); - if ( o == null) { + FreemarkerEmailMessage email = null; + + Object paramValue = (FreemarkerEmailMessage) request.getAttribute("emailMessage"); + if ( paramValue == null) { throw new TemplateModelException( "No email message object found in the request."); } - if ( ! (o instanceof FreemarkerEmailMessage)) { + if ( ! (paramValue instanceof FreemarkerEmailMessage)) { throw new TemplateModelException( "Invalid value for request email attribute"); } - FreemarkerEmailMessage email = (FreemarkerEmailMessage) o; - email.send(subject, html, text); + email = (FreemarkerEmailMessage) paramValue; + + // Read in parameter values. If a value is undefined by the template, the + // default values defined by the email object will be used. + String subject = null; + paramValue = params.get("subject"); + if (paramValue != null && paramValue instanceof SimpleScalar) { + subject = paramValue.toString(); + } + + String html = null; + paramValue = params.get("html"); + if (paramValue != null && paramValue instanceof SimpleScalar) { + html = paramValue.toString(); + } + + String text = null; + paramValue = params.get("text"); + if (paramValue != null && paramValue instanceof SimpleScalar) { + text = paramValue.toString(); + } + + email.send(subject, html, text); } @Override @@ -84,15 +73,17 @@ public class EmailDirective extends BaseTemplateDirectiveModel { Map map = new LinkedHashMap(); map.put("effect", "Create an email message from the parameters set in the invoking template."); + map.put("comment", "Parameter values undefined by the template will be provided by controller default values."); Map params = new HashMap(); - params.put("subject", "email subject"); - params.put("html", "HTML version of email message"); - params.put("text", "Plain text version of email message"); + params.put("subject", "email subject (optional)"); + params.put("html", "HTML version of email message (optional)"); + params.put("text", "Plain text version of email message (optional)"); map.put("parameters", params); - + List examples = new ArrayList(); examples.add("<email subject=\"Password reset confirmation\" html=html text=text>"); + examples.add("<email html=html text=text>"); map.put("examples", examples); return map; From d42acf48d8c3537de134c5c0c42f95ac2df92c34 Mon Sep 17 00:00:00 2001 From: ryounes Date: Wed, 15 Jun 2011 16:31:26 +0000 Subject: [PATCH 26/47] NIHVIVO-2693 Mark code to be removed with a comment --- .../mannlib/vitro/webapp/email/FreemarkerEmailMessage.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java index 5e2ec8597..fac7981cf 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java @@ -253,6 +253,7 @@ public class FreemarkerEmailMessage { } } + // TO BE REMOVED public void send() { String textBody = figureMessageBody(textTemplateName); String htmlBody = figureMessageBody(htmlTemplateName); @@ -303,6 +304,7 @@ public class FreemarkerEmailMessage { * Process the template. If there is no template name or if there is a * problem with the process, return an empty string. */ + // TO BE REMOVED private String figureMessageBody(String templateName) { if (templateName.isEmpty()) { return ""; From 5d587265fae96c82a35279d76fbcf6c8eb2037c4 Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 15 Jun 2011 18:23:07 +0000 Subject: [PATCH 27/47] NIHVIVO-2299 Improve the way Email templates are handled - specify HTML and plain text in the same template. Refine the EmailDirective to permit optional parameters. --- .../admin/UserAccountsAddPageStrategy.java | 6 +- .../admin/UserAccountsEditPageStrategy.java | 33 +-- .../user/UserAccountsCreatePasswordPage.java | 8 +- ...AccountsFirstTimeExternalPageStrategy.java | 7 +- .../UserAccountsMyAccountPageStrategy.java | 7 +- .../user/UserAccountsResetPasswordPage.java | 9 +- .../webapp/email/FreemarkerEmailMessage.java | 195 ++++-------------- .../webapp/web/directives/EmailDirective.java | 123 +++++------ .../userAccounts-acctCreatedEmail-text.ftl | 20 -- ....ftl => userAccounts-acctCreatedEmail.ftl} | 29 ++- ...Accounts-confirmEmailChangedEmail-text.ftl | 10 - ...userAccounts-confirmEmailChangedEmail.ftl} | 19 +- ...erAccounts-firstTimeExternalEmail-text.ftl | 12 -- ...> userAccounts-firstTimeExternalEmail.ftl} | 21 +- ...userAccounts-passwordCreatedEmail-text.ftl | 12 -- ... => userAccounts-passwordCreatedEmail.ftl} | 21 +- .../userAccounts-passwordResetEmail-text.ftl | 12 -- ...tl => userAccounts-passwordResetEmail.ftl} | 21 +- .../userAccounts-resetPasswordEmail-html.ftl | 40 ---- .../userAccounts-resetPasswordEmail-text.ftl | 19 -- 20 files changed, 237 insertions(+), 387 deletions(-) delete mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-text.ftl rename webapp/web/templates/freemarker/body/accounts/{userAccounts-acctCreatedEmail-html.ftl => userAccounts-acctCreatedEmail.ftl} (60%) delete mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail-text.ftl rename webapp/web/templates/freemarker/body/accounts/{userAccounts-confirmEmailChangedEmail-html.ftl => userAccounts-confirmEmailChangedEmail.ftl} (55%) delete mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail-text.ftl rename webapp/web/templates/freemarker/body/accounts/{userAccounts-firstTimeExternalEmail-html.ftl => userAccounts-firstTimeExternalEmail.ftl} (58%) delete mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail-text.ftl rename webapp/web/templates/freemarker/body/accounts/{userAccounts-passwordCreatedEmail-html.ftl => userAccounts-passwordCreatedEmail.ftl} (57%) delete mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-text.ftl rename webapp/web/templates/freemarker/body/accounts/{userAccounts-passwordResetEmail-html.ftl => userAccounts-passwordResetEmail.ftl} (58%) delete mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-html.ftl delete mode 100644 webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-text.ftl diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java index 9061030e7..fe1e1c489 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java @@ -57,6 +57,7 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage { private static class EmailStrategy extends UserAccountsAddPageStrategy { public static final String CREATE_PASSWORD_URL = "/accounts/createPassword"; + private static final String EMAIL_TEMPLATE = "userAccounts-acctCreatedEmail.ftl"; private boolean sentEmail; @@ -91,15 +92,14 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage { Map body = new HashMap(); body.put("userAccount", page.getAddedAccount()); body.put("passwordLink", buildCreatePasswordLink()); - body.put("subjectLine", "Your VIVO account has been created."); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, page.getAddedAccount().getEmailAddress()); email.setSubject("Your VIVO account has been created."); - email.setHtmlTemplate("userAccounts-acctCreatedEmail-html.ftl"); - email.setTextTemplate("userAccounts-acctCreatedEmail-text.ftl"); + email.setTemplate(EMAIL_TEMPLATE); email.setBodyMap(body); + email.processTemplate(); email.send(); sentEmail = true; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java index 3ca3c739c..b043c2422 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java @@ -103,41 +103,22 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { Map body = new HashMap(); body.put("userAccount", page.getUpdatedAccount()); body.put("passwordLink", buildResetPasswordLink()); - - String siteName = getSiteName(); - body.put("siteName", siteName); + body.put("siteName", getSiteName()); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, page.getUpdatedAccount().getEmailAddress()); email.setTemplate(EMAIL_TEMPLATE); - email.setBodyMap(body); - email.setDefaultSubject(getDefaultSubject(siteName)); - email.setDefaultHtml(getDefaultHtml()); - email.setDefaultText(getDefaultText()); - - vreq.setAttribute("email", email); - - email.processTemplate(vreq); + email.setBodyMap(body); + email.processTemplate(); + email.send(); sentEmail = true; } - + private String getSiteName() { - ApplicationBean appBean = vreq.getAppBean(); - return appBean.getApplicationName(); - } - - private String getDefaultSubject(String siteName) { - return siteName + " reset password request"; - } - - private String getDefaultHtml() { - return ""; - } - - private String getDefaultText() { - return "Default text for user accounts edit page"; + ApplicationBean appBean = vreq.getAppBean(); + return appBean.getApplicationName(); } private String buildResetPasswordLink() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java index d134fd737..40ae4d6d0 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java @@ -26,6 +26,7 @@ public class UserAccountsCreatePasswordPage extends .getLog(UserAccountsCreatePasswordPage.class); private static final String TEMPLATE_NAME = "userAccounts-createPassword.ftl"; + private static final String EMAIL_TEMPLATE = "userAccounts-passwordCreatedEmail.ftl"; public UserAccountsCreatePasswordPage(VitroRequest vreq) { super(vreq); @@ -39,7 +40,7 @@ public class UserAccountsCreatePasswordPage extends userAccountsDao.updateUserAccount(userAccount); log.debug("Set password on '" + userAccount.getEmailAddress() + "' to '" + newPassword + "'"); - + notifyUser(); } @@ -56,15 +57,14 @@ public class UserAccountsCreatePasswordPage extends private void notifyUser() { Map body = new HashMap(); body.put("userAccount", userAccount); - body.put("subjectLine", "Password successfully created."); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, userAccount.getEmailAddress()); email.setSubject("Password successfully created."); - email.setHtmlTemplate("userAccounts-passwordCreatedEmail-html.ftl"); - email.setTextTemplate("userAccounts-passwordCreatedEmail-text.ftl"); + email.setTemplate(EMAIL_TEMPLATE); email.setBodyMap(body); + email.processTemplate(); email.send(); } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPageStrategy.java index 71ce98161..975551fdc 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsFirstTimeExternalPageStrategy.java @@ -52,6 +52,8 @@ public abstract class UserAccountsFirstTimeExternalPageStrategy extends public static class EmailStrategy extends UserAccountsFirstTimeExternalPageStrategy { + private static final String EMAIL_TEMPLATE = "userAccounts-firstTimeExternalEmail.ftl"; + public EmailStrategy(VitroRequest vreq, UserAccountsFirstTimeExternalPage page) { super(vreq, page); @@ -66,15 +68,14 @@ public abstract class UserAccountsFirstTimeExternalPageStrategy extends public void notifyUser(UserAccount ua) { Map body = new HashMap(); body.put("userAccount", ua); - body.put("subjectLine", "Your VIVO account has been created."); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, ua.getEmailAddress()); email.setSubject("Your VIVO account has been created."); - email.setHtmlTemplate("userAccounts-firstTimeExternalEmail-html.ftl"); - email.setTextTemplate("userAccounts-firstTimeExternalEmail-text.ftl"); + email.setTemplate(EMAIL_TEMPLATE); email.setBodyMap(body); + email.processTemplate(); email.send(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java index f220d3236..d962165cd 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java @@ -107,6 +107,8 @@ public abstract class UserAccountsMyAccountPageStrategy extends private static final String ERROR_WRONG_PASSWORD_LENGTH = "errorPasswordIsWrongLength"; private static final String ERROR_PASSWORDS_DONT_MATCH = "errorPasswordsDontMatch"; + + private static final String EMAIL_TEMPLATE = "userAccounts-confirmEmailChangedEmail.ftl"; private final String originalEmail; @@ -167,15 +169,14 @@ public abstract class UserAccountsMyAccountPageStrategy extends Map body = new HashMap(); body.put("userAccount", page.getUserAccount()); - body.put("subjectLine", "Your VIVO email account has been changed."); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, page.getUserAccount().getEmailAddress()); email.setSubject("Your VIVO email account has been changed."); - email.setHtmlTemplate("userAccounts-confirmEmailChangedEmail-html.ftl"); - email.setTextTemplate("userAccounts-confirmEmailChangedEmail-text.ftl"); + email.setTemplate(EMAIL_TEMPLATE); email.setBodyMap(body); + email.processTemplate(); email.send(); emailSent = true; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java index 7902cbe5b..3bd511b83 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java @@ -26,6 +26,8 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage private static final String TEMPLATE_NAME = "userAccounts-resetPassword.ftl"; + private static final String EMAIL_TEMPLATE = "userAccounts-passwordResetEmail.ftl"; + protected UserAccountsResetPasswordPage(VitroRequest vreq) { super(vreq); } @@ -38,7 +40,7 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage userAccountsDao.updateUserAccount(userAccount); log.debug("Set password on '" + userAccount.getEmailAddress() + "' to '" + newPassword + "'"); - + notifyUser(); } @@ -55,15 +57,14 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage private void notifyUser() { Map body = new HashMap(); body.put("userAccount", userAccount); - body.put("subjectLine", "Password changed."); FreemarkerEmailMessage email = FreemarkerEmailFactory .createNewMessage(vreq); email.addRecipient(TO, userAccount.getEmailAddress()); email.setSubject("Password changed."); - email.setHtmlTemplate("userAccounts-passwordResetEmail-html.ftl"); - email.setTextTemplate("userAccounts-passwordResetEmail-text.ftl"); + email.setTemplate(EMAIL_TEMPLATE); email.setBodyMap(body); + email.processTemplate(); email.send(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java index fac7981cf..906c46dea 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java @@ -23,17 +23,13 @@ import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException; +import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective; import freemarker.core.Environment; import freemarker.template.Configuration; import freemarker.template.Template; @@ -43,8 +39,14 @@ import freemarker.template.TemplateException; * A framework that makes it simpler to send email messages with a body built * from a Freemarker template. * - * In fact, the body can be plain text from a template, HTML from a template, or - * both. + * The template must contain the @email directive, which may provide the subject + * line, the HTML content, and the plain text content. If these values are not + * provided by the directive, they default to empty strings, or to values that + * were set by the controller. + * + * The directive also calls the send() method here. + * + * @see EmailDirective */ public class FreemarkerEmailMessage { private static final Log log = LogFactory @@ -55,22 +57,16 @@ public class FreemarkerEmailMessage { private final HttpServletRequest req; private final Session session; private final Configuration config; - private final ServletContext ctx; private final List recipients = new ArrayList(); private final InternetAddress replyToAddress; private InternetAddress fromAddress = null; private String subject = ""; - private String defaultSubject = ""; - private String defaultHtml = ""; - private String defaultText = ""; - private String templateName; + private String templateName = ""; + private String htmlContent = ""; + private String textContent = ""; private Map bodyMap = Collections.emptyMap(); - - // TO BE REMOVED - private String htmlTemplateName; - private String textTemplateName; /** * Package access - should only be created by the factory. @@ -81,8 +77,6 @@ public class FreemarkerEmailMessage { this.session = session; this.replyToAddress = replyToAddress; - this.ctx = req.getSession().getServletContext(); - Object o = req.getAttribute(ATTRIBUTE_NAME); if (!(o instanceof Configuration)) { String oClass = (o == null) ? "null" : o.getClass().getName(); @@ -129,46 +123,28 @@ public class FreemarkerEmailMessage { try { recipients.add(new Recipient(type, emailAddress, personalName)); - } catch (AddressException e) { - log.warn("invalid recipient address: " + type + ", '" - + emailAddress + "', personal name '" + personalName + "'"); - return; } catch (UnsupportedEncodingException e) { log.warn("invalid recipient address: " + type + ", '" + emailAddress + "', personal name '" + personalName + "'"); return; } } - - // TO BE REMOVED - public void setHtmlTemplate(String templateName) { - this.htmlTemplateName = nonNull(templateName, ""); - } - - // TO BE REMOVED - public void setTextTemplate(String templateName) { - this.textTemplateName = nonNull(templateName, ""); - } public void setSubject(String subject) { this.subject = nonNull(subject, ""); } - + + public void setHtmlContent(String htmlContent) { + this.htmlContent = nonNull(htmlContent, ""); + } + + public void setTextContent(String textContent) { + this.textContent = nonNull(textContent, ""); + } + public void setTemplate(String templateName) { - this.templateName = nonNull(templateName, ""); + this.templateName = nonNull(templateName, ""); } - - public void setDefaultSubject(String defaultSubject) { - this.defaultSubject = nonNull(defaultSubject, ""); - } - - public void setDefaultHtml(String defaultHtml) { - this.defaultHtml = nonNull(defaultHtml, ""); - } - - public void setDefaultText(String defaultText) { - this.defaultText = nonNull(defaultText, ""); - } public void setBodyMap(Map body) { if (body == null) { @@ -177,87 +153,25 @@ public class FreemarkerEmailMessage { this.bodyMap = new HashMap(body); } } - - public void processTemplate(VitroRequest vreq) { - - vreq.setAttribute("emailMessage", this); - bodyMap.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments()); - bodyMap.put("email", new edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective()); - - try { - Template template = config.getTemplate(templateName); - StringWriter writer = new StringWriter(); - Environment env = template.createProcessingEnvironment(bodyMap, writer); - env.setCustomAttribute("request", vreq); - env.process(); - } catch (TemplateException e) { - log.error(e, e); - } catch (IOException e) { - log.error(e, e); - } - } - - public void send(String subject, String html, String text) { - try { - MimeMessage msg = new MimeMessage(session); - msg.setReplyTo(new Address[] { replyToAddress }); + public void processTemplate() { + bodyMap.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments()); + bodyMap.put("email", new EmailDirective(this)); - if (fromAddress == null) { - msg.addFrom(new Address[] { replyToAddress }); - } else { - msg.addFrom(new Address[] { fromAddress }); - } - - for (Recipient recipient : recipients) { - msg.addRecipient(recipient.type, recipient.address); - } - - if (subject == null) { - log.debug("No email subject specified in template. Using default subject."); - subject = defaultSubject; - } - msg.setSubject(subject); - - if (html == null) { - log.debug("No html email specified in template. Using default html."); - html = defaultHtml; - } - - if (text == null) { - log.debug("No plain text email specified in template. Using default html."); - text = defaultText; - } - - if (StringUtils.isEmpty(text)) { - if (StringUtils.isEmpty(html)) { - log.error("Message has neither text body nor HTML body"); - } else { - msg.setContent(html, "text/html"); - } - } else if (StringUtils.isEmpty(html)) { - msg.setContent(text, "text/plain"); - } else { - MimeMultipart content = new MimeMultipart("alternative"); - addBodyPart(content, text, "text/plain"); - addBodyPart(content, html, "text/html"); - msg.setContent(content); - } - - msg.setSentDate(new Date()); - - Transport.send(msg); - - } catch (MessagingException e) { - log.error("Failed to send message.", e); - } + try { + Template template = config.getTemplate(templateName); + Environment env = template.createProcessingEnvironment(bodyMap, + new StringWriter()); + env.setCustomAttribute("request", req); + env.process(); + } catch (TemplateException e) { + log.error(e, e); + } catch (IOException e) { + log.error(e, e); + } } - // TO BE REMOVED public void send() { - String textBody = figureMessageBody(textTemplateName); - String htmlBody = figureMessageBody(htmlTemplateName); - try { MimeMessage msg = new MimeMessage(session); msg.setReplyTo(new Address[] { replyToAddress }); @@ -274,19 +188,19 @@ public class FreemarkerEmailMessage { msg.setSubject(subject); - if (textBody.isEmpty()) { - if (htmlBody.isEmpty()) { + if (textContent.isEmpty()) { + if (htmlContent.isEmpty()) { log.error("Message has neither text body nor HTML body"); } else { - msg.setContent(htmlBody, "text/html"); + msg.setContent(htmlContent, "text/html"); } } else { - if (htmlBody.isEmpty()) { - msg.setContent(textBody, "text/plain"); + if (htmlContent.isEmpty()) { + msg.setContent(textContent, "text/plain"); } else { MimeMultipart content = new MimeMultipart("alternative"); - addBodyPart(content, textBody, "text/plain"); - addBodyPart(content, htmlBody, "text/html"); + addBodyPart(content, textContent, "text/plain"); + addBodyPart(content, htmlContent, "text/html"); msg.setContent(content); } } @@ -300,27 +214,6 @@ public class FreemarkerEmailMessage { } } - /** - * Process the template. If there is no template name or if there is a - * problem with the process, return an empty string. - */ - // TO BE REMOVED - private String figureMessageBody(String templateName) { - if (templateName.isEmpty()) { - return ""; - } - - try { - TemplateProcessingHelper helper = new TemplateProcessingHelper( - config, req, ctx); - return helper.processTemplate(templateName, bodyMap).toString(); - } catch (TemplateProcessingException e) { - log.warn("Exception while processing email template '" - + templateName + "'", e); - return ""; - } - } - private void addBodyPart(MimeMultipart content, String textBody, String type) throws MessagingException { MimeBodyPart bodyPart = new MimeBodyPart(); @@ -343,7 +236,7 @@ public class FreemarkerEmailMessage { } public Recipient(RecipientType type, String address, String personalName) - throws AddressException, UnsupportedEncodingException { + throws UnsupportedEncodingException { this.type = type; this.address = new InternetAddress(address, personalName); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java index e492d40a7..58ca99ada 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java @@ -9,8 +9,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -22,70 +20,79 @@ import freemarker.template.TemplateException; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; +/** + * Process the inputs for a FreemarkerEmailMessage. + * + * @see FreemarkerEmailMessage + */ public class EmailDirective extends BaseTemplateDirectiveModel { - private static final Log log = LogFactory.getLog(EmailDirective.class); - - @Override - public void execute(Environment env, Map params, TemplateModel[] loopVars, - TemplateDirectiveBody body) throws TemplateException, IOException { + private static final Log log = LogFactory.getLog(EmailDirective.class); - HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request"); - FreemarkerEmailMessage email = null; + private final FreemarkerEmailMessage message; - Object paramValue = (FreemarkerEmailMessage) request.getAttribute("emailMessage"); - if ( paramValue == null) { - throw new TemplateModelException( - "No email message object found in the request."); - } - if ( ! (paramValue instanceof FreemarkerEmailMessage)) { - throw new TemplateModelException( - "Invalid value for request email attribute"); - } - email = (FreemarkerEmailMessage) paramValue; + public EmailDirective(FreemarkerEmailMessage message) { + this.message = message; + } - - // Read in parameter values. If a value is undefined by the template, the - // default values defined by the email object will be used. - String subject = null; - paramValue = params.get("subject"); - if (paramValue != null && paramValue instanceof SimpleScalar) { - subject = paramValue.toString(); - } + @Override + public void execute(Environment env, Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { - String html = null; - paramValue = params.get("html"); - if (paramValue != null && paramValue instanceof SimpleScalar) { - html = paramValue.toString(); - } - - String text = null; - paramValue = params.get("text"); - if (paramValue != null && paramValue instanceof SimpleScalar) { - text = paramValue.toString(); - } + String subject = getOptionalSimpleScalarParameter(params, "subject"); + if (subject != null) { + message.setSubject(subject); + } - email.send(subject, html, text); - } - - @Override - public Map help(String name) { - Map map = new LinkedHashMap(); + String htmlContent = getOptionalSimpleScalarParameter(params, "html"); + if (htmlContent != null) { + message.setHtmlContent(htmlContent); + } - map.put("effect", "Create an email message from the parameters set in the invoking template."); - map.put("comment", "Parameter values undefined by the template will be provided by controller default values."); - - Map params = new HashMap(); - params.put("subject", "email subject (optional)"); - params.put("html", "HTML version of email message (optional)"); - params.put("text", "Plain text version of email message (optional)"); - map.put("parameters", params); + String textContent = getOptionalSimpleScalarParameter(params, "text"); + if (textContent != null) { + message.setTextContent(textContent); + } - List examples = new ArrayList(); - examples.add("<email subject=\"Password reset confirmation\" html=html text=text>"); + if ((htmlContent == null) && (textContent == null)) { + throw new TemplateModelException("The email directive must have " + + "either a 'html' parameter or a 'text' parameter."); + } + } + + private String getOptionalSimpleScalarParameter(Map params, + String name) throws TemplateModelException { + Object o = params.get(name); + if (o == null) { + return null; + } + + if (!(o instanceof SimpleScalar)) { + throw new TemplateModelException("The '" + name + "' parameter " + + "for the email directive must be a string value."); + } + + return o.toString(); + } + + @Override + public Map help(String name) { + Map map = new LinkedHashMap(); + + map.put("effect", + "Create an email message from the parameters set in the invoking template."); + + Map params = new HashMap(); + params.put("subject", "email subject (optional)"); + params.put("html", "HTML version of email message (optional)"); + params.put("text", "Plain text version of email message (optional)"); + map.put("parameters", params); + + List examples = new ArrayList(); + examples.add("<email subject=\"Password reset confirmation\" html=html text=text>"); examples.add("<email html=html text=text>"); - map.put("examples", examples); - - return map; - } + map.put("examples", examples); + + return map; + } } diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-text.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-text.ftl deleted file mode 100644 index 69b8d5f30..000000000 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-text.ftl +++ /dev/null @@ -1,20 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -<#-- Confirmation that an account has been created. --> - -${userAccount.firstName} ${userAccount.lastName} - -Congratulations! - -We have created your new VIVO account associated with -${userAccount.emailAddress}. - -If you did not request this new account you can safely ignore this email. -This request will expire if not acted upon for 30 days. - -Paste the link below into your browser's address bar to create your password -for your new account using our secure server. - -${passwordLink} - -Thanks! diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail.ftl similarity index 60% rename from webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-html.ftl rename to webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail.ftl index 5fa2c5f44..4aa355468 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail-html.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-acctCreatedEmail.ftl @@ -2,9 +2,12 @@ <#-- Confirmation that an account has been created. --> +<#assign subject = "Your VIVO account has been created." /> + +<#assign html> - ${subjectLine} + ${subject}

@@ -40,4 +43,26 @@ Thanks!

- \ No newline at end of file + + + +<#assign text> +${userAccount.firstName} ${userAccount.lastName} + +Congratulations! + +We have created your new VIVO account associated with +${userAccount.emailAddress}. + +If you did not request this new account you can safely ignore this email. +This request will expire if not acted upon for 30 days. + +Paste the link below into your browser's address bar to create your password +for your new account using our secure server. + +${passwordLink} + +Thanks! + + +<@email subject=subject html=html text=text /> \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail-text.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail-text.ftl deleted file mode 100644 index 78f1457bf..000000000 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail-text.ftl +++ /dev/null @@ -1,10 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -<#-- Confirmation that the user has changed his email account. --> - -Hi, ${userAccount.firstName} ${userAccount.lastName} - -You recently changed the email address associated with -${userAccount.firstName} ${userAccount.lastName} - -Thank you. diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail.ftl similarity index 55% rename from webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail-html.ftl rename to webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail.ftl index e06f7e1ae..9acec6fcf 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail-html.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-confirmEmailChangedEmail.ftl @@ -2,9 +2,12 @@ <#-- Confirmation that the user has changed his email account. --> +<#assign subject = "Your VIVO email account has been changed." /> + +<#assign html> - ${subjectLine} + ${subject}

@@ -20,4 +23,16 @@ Thank you.

- \ No newline at end of file + + + +<#assign text> +Hi, ${userAccount.firstName} ${userAccount.lastName} + +You recently changed the email address associated with +${userAccount.firstName} ${userAccount.lastName} + +Thank you. + + +<@email subject=subject html=html text=text /> \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail-text.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail-text.ftl deleted file mode 100644 index 8b788d56d..000000000 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail-text.ftl +++ /dev/null @@ -1,12 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -<#-- Confirmation that an account has been created for an externally-authenticated user. --> - -${userAccount.firstName} ${userAccount.lastName} - -Congratulations! - -We have created your new VIVO account associated with -${userAccount.emailAddress}. - -Thanks! diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail.ftl similarity index 58% rename from webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail-html.ftl rename to webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail.ftl index 5faa53dff..434c65851 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail-html.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternalEmail.ftl @@ -2,9 +2,12 @@ <#-- Confirmation that an account has been created for an externally-authenticated user. --> +<#assign subject = "Your VIVO account has been created." /> + +<#assign html> - ${subjectLine} + ${subject}

@@ -23,4 +26,18 @@ Thanks!

- \ No newline at end of file + + + +<#assign text> +${userAccount.firstName} ${userAccount.lastName} + +Congratulations! + +We have created your new VIVO account associated with +${userAccount.emailAddress}. + +Thanks! + + +<@email subject=subject html=html text=text /> \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail-text.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail-text.ftl deleted file mode 100644 index 2a339d4a9..000000000 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail-text.ftl +++ /dev/null @@ -1,12 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -<#-- Confirmation that a password has been created. --> - -${userAccount.firstName} ${userAccount.lastName} - -Password successfully created. - -Your new password associated with ${userAccount.emailAddress} -has been created. - -Thank you. diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail.ftl similarity index 57% rename from webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail-html.ftl rename to webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail.ftl index 1773766e9..a99c51e08 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail-html.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordCreatedEmail.ftl @@ -2,9 +2,12 @@ <#-- Confirmation that an password has been created. --> +<#assign subject = "Password successfully created." /> + +<#assign html> - ${subjectLine} + ${subject}

@@ -23,4 +26,18 @@ Thank you.

- \ No newline at end of file + + + +<#assign text> +${userAccount.firstName} ${userAccount.lastName} + +Password successfully created. + +Your new password associated with ${userAccount.emailAddress} +has been created. + +Thank you. + + +<@email subject=subject html=html text=text /> \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-text.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-text.ftl deleted file mode 100644 index cfe0cd00f..000000000 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-text.ftl +++ /dev/null @@ -1,12 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -<#-- Confirmation that a password has been reset. --> - -${userAccount.firstName} ${userAccount.lastName} - -Password successfully changed. - -Your new password associated with ${userAccount.emailAddress} -has been changed. - -Thank you. diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail.ftl similarity index 58% rename from webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-html.ftl rename to webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail.ftl index 49c4eb531..6650ccd8e 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail-html.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-passwordResetEmail.ftl @@ -2,9 +2,12 @@ <#-- Confirmation that a password has been reset. --> +<#assign subject = "Password changed." /> + +<#assign html> - ${subjectLine} + ${subject}

@@ -23,4 +26,18 @@ Thank you.

- \ No newline at end of file + + + +<#assign text> +${userAccount.firstName} ${userAccount.lastName} + +Password successfully changed. + +Your new password associated with ${userAccount.emailAddress} +has been changed. + +Thank you. + + +<@email subject=subject html=html text=text /> \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-html.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-html.ftl deleted file mode 100644 index 0fa37fba3..000000000 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-html.ftl +++ /dev/null @@ -1,40 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -<#-- Notification that your password has been reset. --> - - - - ${subjectLine} - - -

- ${userAccount.firstName} ${userAccount.lastName} -

- -

- We received a request to reset the password for your account (${userAccount.emailAddress}). - Please follow the instructions below to proceed with your password reset. -

- -

- If you did not request this new account you can safely ignore this email. - This request will expire if not acted upon for 30 days. -

- -

- Click the link below to reset your password using our secure server. -

- -

- ${passwordLink} -

- -

- If the link above doesn't work, you can copy and paste the link directly into your browser's address bar. -

- -

- Thank you! -

- - \ No newline at end of file diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-text.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-text.ftl deleted file mode 100644 index 82624c327..000000000 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-resetPasswordEmail-text.ftl +++ /dev/null @@ -1,19 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -<#-- Notification that your password has been reset. --> - -${userAccount.firstName} ${userAccount.lastName} - -We received a request to reset the password for your account -(${userAccount.emailAddress}). -Please follow the instructions below to proceed with your password reset. - -If you did not request this new account you can safely ignore this email. -This request will expire if not acted upon for 30 days. - -Paste the link below into your browser's address bar to reset your password -using our secure server. - -${passwordLink} - -Thank you! From 2bbaf97408f9f8469b835769f7bc1e6ded7014ba Mon Sep 17 00:00:00 2001 From: runeliza Date: Wed, 15 Jun 2011 18:33:23 +0000 Subject: [PATCH 28/47] Some cleanup of JSONReconcileServlet. Added new servlet GrefinePropertyListServlet for servicing Google Refine's "Add columns from VIVO" requests. --- .../GrefinePropertyListServlet.java | 753 ++++++++++++++++++ .../controller/JSONReconcileServlet.java | 31 +- 2 files changed, 773 insertions(+), 11 deletions(-) create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/controller/GrefinePropertyListServlet.java diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/GrefinePropertyListServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/GrefinePropertyListServlet.java new file mode 100644 index 000000000..7a5baf6f5 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/GrefinePropertyListServlet.java @@ -0,0 +1,753 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.index.Term; +import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.queryParser.QueryParser; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.TopDocs; +import org.apache.lucene.search.WildcardQuery; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import com.hp.hpl.jena.vocabulary.OWL; + +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; +import edu.cornell.mannlib.vitro.webapp.beans.Datatype; +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.Ontology; +import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao; +import edu.cornell.mannlib.vitro.webapp.dao.DatatypeDao; +import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; +import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao; +import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; +import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.search.SearchException; +import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc; +import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc.VitroLuceneTermNames; +import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory; +import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneSetup; + +/** + * This servlet is for servicing Google Refine's + * "Add columns from VIVO" requests. + * + * @author Eliza Chan (elc2013@med.cornell.edu) + * + */ +public class GrefinePropertyListServlet extends VitroHttpServlet { + + private int MAXDEPTH = 7; + private int NUM_COLS = 9; + private static String QUERY_PARAMETER_NAME = "term"; + public static final int MAX_QUERY_LENGTH = 500; + private static final Log log = LogFactory.getLog(GrefinePropertyListServlet.class.getName()); + + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + //resp.setContentType("application/json"); + super.doPost(req, resp); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.doGet(req, resp); + resp.setContentType("application/json"); + VitroRequest vreq = new VitroRequest(req); + + try { + + String callbackStr = (vreq.getParameter("callback") == null) ? "" + : vreq.getParameter("callback"); + ServletOutputStream out = resp.getOutputStream(); + + + // ******* + // methodology adopted from DatatypePropertiesListingController and ClassHierarchyListingController + // ******* + VClassDao vcDao = vreq.getFullWebappDaoFactory().getVClassDao(); + DataPropertyDao dao = vreq.getFullWebappDaoFactory().getDataPropertyDao(); + String topUri = vreq.getParameter("type"); + VClass topClass = vcDao.getVClassByURI(topUri); + HashSet propURIs = new HashSet(); + HashMap> classPropertiesMap = + populateClassPropertiesMap(vcDao, dao, topUri, propURIs); + + + // Construct json String + JSONObject completeJson = new JSONObject(); + JSONArray propertiesJsonArr = new JSONArray(); + if (classPropertiesMap.size() > 0) { + for (Iterator iter = classPropertiesMap.keySet().iterator(); iter.hasNext();) { // add results to schema + VClass vc = (VClass) iter.next(); + System.out.println("vc uri: " + vc.getURI()); + System.out.println("vc name: " + vc.getName()); + + ArrayList vcProps = (ArrayList)classPropertiesMap.get(vc); + for (DataProperty prop: vcProps) { + String nameStr = prop.getPublicName()==null ? prop.getName()==null ? null : prop.getName() : prop.getPublicName(); + System.out.println("--- uri: " + prop.getURI()); + System.out.println("--- name: " + nameStr); + // top level + JSONObject propertiesItemJson = new JSONObject(); + JSONObject rootSchemaJson = new JSONObject(); + rootSchemaJson.put("id", vc.getURI()); + rootSchemaJson.put("name", vc.getName()); + rootSchemaJson.put("alias", new JSONArray()); + propertiesItemJson.put("schema", rootSchemaJson); + // second level + propertiesItemJson.put("id", prop.getURI()); + propertiesItemJson.put("name", nameStr); + propertiesItemJson.put("alias", new JSONArray()); + + JSONObject expectsJson = new JSONObject(); + expectsJson.put("id", prop.getURI()); + expectsJson.put("name", nameStr); + expectsJson.put("alias", new JSONArray()); + propertiesItemJson.put("expects", expectsJson); + + propertiesJsonArr.put(propertiesItemJson); + } + } + } + + + // get data properties from subclasses + List lvl2Classes = new ArrayList(); + List roots = null; + String requestType = vreq.getParameter("type"); + if (requestType != null) { + roots = new LinkedList(); + roots.add(vcDao.getVClassByURI(requestType)); + } + + if (roots != null) { + String ontologyUri = null; + Collections.sort(roots); + Iterator rootIt = roots.iterator(); + if (rootIt.hasNext()) { + while (rootIt.hasNext()) { + VClass root = (VClass) rootIt.next(); + if (root != null) { + List lvl2ChildClasses = new ArrayList(); + addChildren(vcDao, vreq.getFullWebappDaoFactory(), root, lvl2ChildClasses, 0, ontologyUri); + lvl2Classes.addAll(lvl2ChildClasses); + } + } + } + } + + + for (VClass lvl2Class: lvl2Classes) { + HashMap> lvl2ClassPropertiesMap = + populateClassPropertiesMap(vcDao, dao, lvl2Class.getURI(), propURIs); + if (lvl2ClassPropertiesMap.size() > 0) { + for (Iterator iter = lvl2ClassPropertiesMap.keySet().iterator(); iter.hasNext();) { // add results to schema + VClass vc = (VClass) iter.next(); + ArrayList vcProps = (ArrayList)lvl2ClassPropertiesMap.get(vc); + for (DataProperty prop: vcProps) { + String nameStr = prop.getPublicName()==null ? prop.getName()==null ? null : prop.getName() : prop.getPublicName(); + // top level + JSONObject propertiesItemJson = new JSONObject(); + + JSONObject rootSchemaJson = new JSONObject(); + rootSchemaJson.put("id", topClass.getURI()); + rootSchemaJson.put("name", topClass.getName()); + rootSchemaJson.put("alias", new JSONArray()); + propertiesItemJson.put("schema", rootSchemaJson); + + // second level + propertiesItemJson.put("id", vc.getURI()); + propertiesItemJson.put("name", vc.getName()); + propertiesItemJson.put("alias", new JSONArray()); + + propertiesItemJson.put("id2", prop.getURI()); + propertiesItemJson.put("name2", nameStr); + propertiesItemJson.put("alias2", new JSONArray()); + + JSONObject expectsJson = new JSONObject(); + expectsJson.put("id", prop.getURI()); + expectsJson.put("name", nameStr); + expectsJson.put("alias", new JSONArray()); + propertiesItemJson.put("expects", expectsJson); + + propertiesJsonArr.put(propertiesItemJson); + } + } + + } + } + + completeJson.put("properties", propertiesJsonArr); + out.print(callbackStr + "(" + completeJson.toString() + ")"); + + + + } catch (Exception ex) { + log.warn(ex, ex); + } + } + + + private HashMap> populateClassPropertiesMap ( + VClassDao vcDao, + DataPropertyDao dao, + String uri, + HashSet propURIs) { + + HashMap> classPropertiesMap = new HashMap>(); + List props = new ArrayList(); + VClass topVc = vcDao.getVClassByURI(uri); + Collection dataProps = dao.getDataPropertiesForVClass(uri); + Iterator dataPropIt = dataProps.iterator(); + while (dataPropIt.hasNext()) { + DataProperty dp = dataPropIt.next(); + if (!(propURIs.contains(dp.getURI()))) { + propURIs.add(dp.getURI()); + DataProperty prop = dao.getDataPropertyByURI(dp.getURI()); + if (prop != null) { + props.add(prop); + } + } + } + + + if (props.size() > 0) { + + Collections.sort(props); + for (DataProperty prop: props) { + String nameStr = prop.getPublicName()==null ? prop.getName()==null ? null : prop.getName() : prop.getPublicName(); + if (nameStr != null) { + if (prop.getDomainClassURI() != null) { + VClass vc = vcDao.getVClassByURI(prop.getDomainClassURI()); + if (classPropertiesMap.get(vc) != null) { + ArrayList existingList = (ArrayList)classPropertiesMap.get(vc); + existingList.add(prop); + } else { + ArrayList newList = new ArrayList(); + newList.add(prop); + classPropertiesMap.put(vc, newList); + } + + } else { // some properties have no domain, belong to top vc by default + if (classPropertiesMap.get(topVc) != null) { + ArrayList existingList = (ArrayList)classPropertiesMap.get(topVc); + existingList.add(prop); + } else { + ArrayList newList = new ArrayList(); + newList.add(prop); + classPropertiesMap.put(topVc, newList); + } + } + } + } + } + return classPropertiesMap; + } + + private void addChildren(VClassDao vcDao, WebappDaoFactory wadf, VClass parent, List list, int position, String ontologyUri) { + List rowElts = addVClassDataToResultsList(wadf, parent, position, ontologyUri); + int childShift = (rowElts.size() > 0) ? 1 : 0; // if addVClassDataToResultsList filtered out the result, don't shift the children over + list.addAll(rowElts); + List childURIstrs = vcDao.getSubClassURIs(parent.getURI()); + if ((childURIstrs.size()>0) && position addVClassDataToResultsList(WebappDaoFactory wadf, VClass vcw, int position, String ontologyUri) { + List results = new ArrayList(); + if (ontologyUri == null || ( (vcw.getNamespace()!=null) && (vcw.getNamespace().equals(ontologyUri)) ) ) { + results.add(vcw); + +/* + for (int i=0; i"+vcw.getLocalNameWithPrefix()+""), results, numCols); + } catch (Exception e) { + numCols = addColToResults(((vcw.getLocalNameWithPrefix() == null) ? "" : vcw.getLocalNameWithPrefix()), results, numCols); // column 2 + } + numCols = addColToResults(((vcw.getShortDef() == null) ? "" : vcw.getShortDef()), results, numCols); // column 3 + numCols = addColToResults(((vcw.getExample() == null) ? "" : vcw.getExample()), results, numCols); // column 4 + + // Get group name if it exists + VClassGroupDao groupDao= wadf.getVClassGroupDao(); + String groupURI = vcw.getGroupURI(); + String groupName = null; + VClassGroup classGroup = null; + if(groupURI != null) { + classGroup = groupDao.getGroupByURI(groupURI); + if (classGroup != null) { + groupName = classGroup.getPublicName(); + } + } + numCols = addColToResults(((groupName == null) ? "" : groupName), results, numCols); // column 5 + + // Get ontology name + String ontName = null; + try { + OntologyDao ontDao = wadf.getOntologyDao(); + Ontology ont = ontDao.getOntologyByURI(vcw.getNamespace()); + ontName = ont.getName(); + } catch (Exception e) {} + numCols = addColToResults(((ontName == null) ? "" : ontName), results, numCols); // column 6 + + numCols = addColToResults(vcw.getHiddenFromDisplayBelowRoleLevel() == null ? "unspecified" : vcw.getHiddenFromDisplayBelowRoleLevel().getShorthand(), results, numCols); // column 7 + numCols = addColToResults(vcw.getProhibitedFromUpdateBelowRoleLevel() == null ? "unspecified" : vcw.getProhibitedFromUpdateBelowRoleLevel().getShorthand(), results, numCols); // column 8 + + results.add("XX"); // column 9 +*/ + } + return results; + } + + private Integer addColToResults (String value, List results, Integer colIndex) { + if (colIndex>0) { + results.add(value); + } + return colIndex-1; + } + + protected JSONObject getResult(VitroRequest vreq, HttpServletRequest req, + HttpServletResponse resp) throws ServletException { + + HashMap searchWithTypeMap = new HashMap(); + HashMap searchNoTypeMap = new HashMap(); + ArrayList queries = new ArrayList(); + Object qObj = vreq.getParameter("queries"); + + if (qObj == null) { + qObj = vreq.getParameter("query"); + } + + if (qObj != null && qObj instanceof String) { + // e.g. + // {"q0":{"query":"Cathleen","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"}, + // "q1":{"query":"Geoffrey","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"}, + // "q2":{"query":"Dina","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"}} + String qStr = (String) qObj; + queries.add(qStr); + } + + try { + for (int i = 0; i < queries.size(); i++) { + String queryStr = (String) queries.get(i); + JSONObject json = new JSONObject(queryStr); + + if (json.has("query")) { // single query + if (json.has("type")) { + searchWithTypeMap.put("query", json); + } else { + // user did not specify a type + searchNoTypeMap.put("query", json); + } + } else { // multiple queries + for (Iterator iter = json.keys(); iter.hasNext();) { + ArrayList jsonList = new ArrayList(); + String key = (String) iter.next(); + Object obj = json.get(key); + JSONObject jsonLvl2 = (JSONObject) obj; + if (jsonLvl2.has("query")) { + if (jsonLvl2.has("type")) { + searchWithTypeMap.put(key, jsonLvl2); + } else { + // user did not specify a type + searchNoTypeMap.put(key, jsonLvl2); + } + } + } + } + } + } catch (JSONException ex) { + System.err.println("JSONReconcileServlet JSONException: " + ex); + throw new ServletException("JSONReconcileServlet JSONException: " + + ex); + } + + // Run index search + JSONObject qJson = null; + if (searchWithTypeMap.size() > 0) { + qJson = runSearch(searchWithTypeMap, vreq); + } else { + qJson = runSearch(searchNoTypeMap, vreq); + } + return qJson; + } + + /** + * Returns a default JSON response. + * + * @param req + * @param resp + * @return + * @throws ServletException + */ + protected JSONObject getMetadata(HttpServletRequest req, HttpServletResponse resp, String defaultNamespace, + String defaultTypeList, String serverName, int serverPort) throws ServletException { + + JSONObject json = new JSONObject(); + try { + json.put("name", "VIVO Reconciliation Service"); + if (defaultNamespace != null) { + json.put("identifierSpace", defaultNamespace); + json.put("schemaSpace", defaultNamespace); + } + JSONObject viewJson = new JSONObject(); + StringBuffer urlBuf = new StringBuffer(); + urlBuf.append("http://" + serverName); + if (serverPort == 8080) { + urlBuf.append(":" + serverPort); + } + if (req.getContextPath() != null) { + urlBuf.append(req.getContextPath()); + } + viewJson.put("url", urlBuf.toString() + "/individual?uri={{id}}"); + json.put("view", viewJson); + + // parse defaultTypeList from deploy.properties + if (defaultTypeList != null) { + String[] splitList = defaultTypeList.split(";"); + String[][] idNameArray = new String[splitList.length][splitList.length]; + for(int i = 0; i currMap, + VitroRequest vreq) throws ServletException { + JSONObject qJson = new JSONObject(); + try { + Analyzer analyzer = getAnalyzer(getServletContext()); + IndexSearcher searcherForRequest = LuceneIndexFactory + .getIndexSearcher(getServletContext()); + + for (Map.Entry entry : currMap.entrySet()) { + JSONObject resultAllJson = new JSONObject(); + String key = entry.getKey(); + JSONObject json = (JSONObject) entry.getValue(); + String queryVal = json.getString("query"); + + // continue with properties list + String searchType = null; + int limit = 3; // default + String typeStrict = "should"; // default + ArrayList propertiesList = new ArrayList(); + + if (json.has("type")) { + searchType = json.getString("type"); + } + if (json.has("limit")) { + limit = json.getInt("limit"); + } + if (json.has("type_strict")) { // Not sure what this variable + // represents. Skip for now. + typeStrict = json.getString("type_strict"); + } + if (json.has("properties")) { + JSONArray properties = json.getJSONArray("properties"); + for (int i = 0; i < properties.length(); i++) { + String[] pvPair = new String[2]; + JSONObject jsonProperty = properties.getJSONObject(i); + String pid = jsonProperty.getString("pid"); + String v = jsonProperty.getString("v"); + pvPair[0] = pid; + pvPair[1] = v; + propertiesList.add(pvPair); + } + } + + // begin search + JSONArray resultJsonArr = new JSONArray(); + Query query = getReconcileQuery(vreq, analyzer, + queryVal, searchType, propertiesList); + + TopDocs topDocs = searcherForRequest.search(query, null, limit); + if (topDocs != null && topDocs.scoreDocs != null) { + int hitsLength = topDocs.scoreDocs.length; + if (hitsLength > 0) { + for (int i = 0; i < topDocs.scoreDocs.length; i++) { + JSONObject resultJson = new JSONObject(); + float score = topDocs.scoreDocs[i].score; + resultJson.put("score", score); + + Document doc = searcherForRequest + .doc(topDocs.scoreDocs[i].doc); + String uri = doc.get(Entity2LuceneDoc.term.URI); + IndividualDao iDao = vreq.getWebappDaoFactory() + .getIndividualDao(); + Individual ind = iDao.getIndividualByURI(uri); + if (ind != null) { + String name = ind.getName(); + // encode # to %23 + String modUri = uri.replace("#", "%23"); + resultJson.put("id", modUri); + resultJson.put("name", name); + } + List fields = doc.getFields(); + JSONArray typesJsonArr = new JSONArray(); + for (int j = 0; j < fields.size(); j++) { + Field field = (Field) fields.get(j); + String fieldName = field.name(); + if ("type".equals(fieldName)) { + // e.g. http://aims.fao.org/aos/geopolitical.owl#area + String type = field.stringValue(); + int lastIndex2 = type.lastIndexOf('/') + 1; + String typeName = type + .substring(lastIndex2); + typeName = typeName.replace("#", ":"); + JSONObject typesJson = new JSONObject(); + typesJson.put("id", type); + typesJson.put("name", typeName); + typesJsonArr.put(typesJson); + } + } + resultJson.put("type", typesJsonArr); + resultJson.put("match", "false"); + resultJsonArr.put(resultJson); + } + } + } + resultAllJson.put("result", resultJsonArr); + qJson.put(key, resultAllJson); + } + + } catch (JSONException ex) { + System.err.println("JSONReconcileServlet JSONException: " + ex); + throw new ServletException("JSONReconcileServlet JSONException: " + + ex); + } catch (SearchException ex) { + System.err.println("JSONReconcileServlet SearchException: " + ex); + throw new ServletException("JSONReconcileServlet SearchException: " + + ex); + } catch (IOException ex) { + System.err.println("JSONReconcileServlet IOException: " + ex); + throw new ServletException("JSONReconcileServlet IOException: " + + ex); + } + + return qJson; + } + + private Analyzer getAnalyzer(ServletContext servletContext) + throws SearchException { + Object obj = servletContext.getAttribute(LuceneSetup.ANALYZER); + if (obj == null || !(obj instanceof Analyzer)) + throw new SearchException("Could not get anlyzer"); + else + return (Analyzer) obj; + } + + private Query makeReconcileNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) { + + /* Original code + String tokenizeParam = (String) request.getParameter("tokenize"); + boolean tokenize = "true".equals(tokenizeParam); + + // Note: Stemming is only relevant if we are tokenizing: an untokenized name + // query will not be stemmed. So we don't look at the stem parameter until we get to + // makeTokenizedNameQuery(). + if (tokenize) { + return makeTokenizedNameQuery(querystr, analyzer, request); + } else { + return makeUntokenizedNameQuery(querystr); + } + */ + + // modified code for reconciliation service + request.setAttribute("stem", true); + return makeTokenizedNameQuery(querystr, analyzer, request); + } + + private Query makeTokenizedNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) { + + String stemParam = (String) request.getParameter("stem"); + boolean stem = "true".equals(stemParam); + String termName = stem ? VitroLuceneTermNames.NAME_STEMMED : VitroLuceneTermNames.NAME_UNSTEMMED; + + BooleanQuery boolQuery = new BooleanQuery(); + + // Use the query parser to analyze the search term the same way the indexed text was analyzed. + // For example, text is lowercased, and function words are stripped out. + QueryParser parser = getQueryParser(termName, analyzer); + + // The wildcard query doesn't play well with stemming. Query term name:tales* doesn't match + // "tales", which is indexed as "tale", while query term name:tales does. Obviously we need + // the wildcard for name:tal*, so the only way to get them all to match is use a disjunction + // of wildcard and non-wildcard queries. The query will look have only an implicit disjunction + // operator: e.g., +(name:tales name:tales*) + try { + log.debug("Adding non-wildcard query for " + querystr); + Query query = parser.parse(querystr); + boolQuery.add(query, BooleanClause.Occur.SHOULD); + + // Prevent ParseException here when adding * after a space. + // If there's a space at the end, we don't need the wildcard query. + if (! querystr.endsWith(" ")) { + log.debug("Adding wildcard query for " + querystr); + Query wildcardQuery = parser.parse(querystr + "*"); + boolQuery.add(wildcardQuery, BooleanClause.Occur.SHOULD); + } + + log.debug("Name query is: " + boolQuery.toString()); + } catch (ParseException e) { + log.warn(e, e); + } + + + return boolQuery; + } + + private Query makeUntokenizedNameQuery(String querystr) { + + querystr = querystr.toLowerCase(); + String termName = VitroLuceneTermNames.NAME_LOWERCASE; + BooleanQuery query = new BooleanQuery(); + log.debug("Adding wildcard query on unanalyzed name"); + query.add( + new WildcardQuery(new Term(termName, querystr + "*")), + BooleanClause.Occur.MUST); + + return query; + } + + private QueryParser getQueryParser(String searchField, Analyzer analyzer){ + // searchField indicates which field to search against when there is no term + // indicated in the query string. + // The analyzer is needed so that we use the same analyzer on the search queries as + // was used on the text that was indexed. + QueryParser qp = new QueryParser(searchField,analyzer); + //this sets the query parser to AND all of the query terms it finds. + qp.setDefaultOperator(QueryParser.AND_OPERATOR); + return qp; + } + + private Query getReconcileQuery(VitroRequest request, Analyzer analyzer, + String querystr, String typeParam, ArrayList propertiesList) throws SearchException{ + + Query query = null; + try { + if( querystr == null){ + log.error("There was no Parameter '"+ QUERY_PARAMETER_NAME + +"' in the request."); + return null; + }else if( querystr.length() > MAX_QUERY_LENGTH ){ + log.debug("The search was too long. The maximum " + + "query length is " + MAX_QUERY_LENGTH ); + return null; + } + + + query = makeReconcileNameQuery(querystr, analyzer, request); + + + // filter by type + if (typeParam != null) { + BooleanQuery boolQuery = new BooleanQuery(); + boolQuery.add( new TermQuery( + new Term(VitroLuceneTermNames.RDFTYPE, + typeParam)), + BooleanClause.Occur.MUST); + boolQuery.add(query, BooleanClause.Occur.MUST); + query = boolQuery; + } + + // if propertiesList has elements, add extra queries to query + Iterator it = propertiesList.iterator(); + while (it.hasNext()) { + String[] pvPair = it.next(); + Query extraQuery = makeReconcileNameQuery(pvPair[1], analyzer, request); + if (!"".equals(pvPair[0]) && pvPair[0] != null) { + BooleanQuery boolQuery = new BooleanQuery(); + boolQuery.add(new TermQuery(new Term( + VitroLuceneTermNames.RDFTYPE, pvPair[0])), + BooleanClause.Occur.MUST); + boolQuery.add(extraQuery, BooleanClause.Occur.MUST); + extraQuery = boolQuery; + } + ((BooleanQuery)query).add(extraQuery, BooleanClause.Occur.MUST); + } + } catch (Exception ex) { + throw new SearchException(ex.getMessage()); + } + + return query; + } + +} + diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java index fe4b9f63b..c3ea6360e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java @@ -70,14 +70,14 @@ public class JSONReconcileServlet extends VitroHttpServlet { super.doGet(req, resp); resp.setContentType("application/json"); VitroRequest vreq = new VitroRequest(req); - System.out.println("vreq"); - System.out.println(vreq.getWebappDaoFactory()); - +// System.out.println("vreq"); +// System.out.println(vreq.getWebappDaoFactory()); + try { if (vreq.getParameter("query") != null || vreq.getParameter("queries") != null) { JSONObject qJson = getResult(vreq, req, resp); - System.out.println("result: " + qJson.toString()); +// System.out.println("result: " + qJson.toString()); String responseStr = (vreq.getParameter("callback") == null) ? qJson .toString() : vreq.getParameter("callback") + "(" + qJson.toString() + ")"; @@ -85,14 +85,23 @@ public class JSONReconcileServlet extends VitroHttpServlet { out.print(responseStr); } else { // metadata String defaultNamespace = null; - String defaultTypeList = null; + //String defaultTypeList = null; String serverName = null; int serverPort = req.getServerPort(); if (vreq.getWebappDaoFactory() != null) { defaultNamespace = vreq.getWebappDaoFactory().getDefaultNamespace(); } - defaultTypeList = ConfigurationProperties.getBean(req).getProperty("Vitro.reconcile.defaultTypeList"); + String defaultTypeList = + ConfigurationProperties.getBean(getServletContext()).getProperty("Vitro.reconcile.defaultTypeList"); + + //defaultTypeList = + // "http://vivoweb.org/ontology/core#Course, Course; " + + // "http://vivoweb.org/ontology/core#Grant, Grant; " + + // "http://aims.fao.org/aos/geopolitical.owl, Location; " + + // "http://xmlns.com/foaf/0.1/Organization, Organization; " + + // "http://xmlns.com/foaf/0.1/Person, Person; " + + // "http://purl.org/ontology/bibo/Article, Publication"; serverName = req.getServerName(); JSONObject metaJson = getMetadata(req, resp, defaultNamespace, defaultTypeList, serverName, serverPort); String callbackStr = (vreq.getParameter("callback") == null) ? "" @@ -124,8 +133,8 @@ public class JSONReconcileServlet extends VitroHttpServlet { // "q2":{"query":"Dina","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"}} String qStr = (String) qObj; queries.add(qStr); - System.out.println(); - System.out.println("query: " + qStr + "\n"); +// System.out.println(); +// System.out.println("query: " + qStr + "\n"); } try { @@ -293,8 +302,7 @@ public class JSONReconcileServlet extends VitroHttpServlet { Individual ind = iDao.getIndividualByURI(uri); if (ind != null) { String name = ind.getName(); - // encode # to %23 - String modUri = uri.replace("#", "%23"); + String modUri = uri.replace("#", "%23"); // encodes # to %23 resultJson.put("id", modUri); resultJson.put("name", name); } @@ -430,7 +438,7 @@ public class JSONReconcileServlet extends VitroHttpServlet { // indicated in the query string. // The analyzer is needed so that we use the same analyzer on the search queries as // was used on the text that was indexed. - QueryParser qp = new QueryParser(Version.LUCENE_29, searchField,analyzer); + QueryParser qp = new QueryParser(searchField,analyzer); //this sets the query parser to AND all of the query terms it finds. qp.setDefaultOperator(QueryParser.AND_OPERATOR); return qp; @@ -489,3 +497,4 @@ public class JSONReconcileServlet extends VitroHttpServlet { } } + From 738a177cb88df2c95eec52d9e619e75377151ef8 Mon Sep 17 00:00:00 2001 From: manolobevia Date: Wed, 15 Jun 2011 18:59:34 +0000 Subject: [PATCH 29/47] NIHVIVO-2280: Styled first time log in for external auth. --- .../body/accounts/userAccounts-firstTimeExternal.ftl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl index 8367ca164..fed4e4486 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-firstTimeExternal.ftl @@ -38,17 +38,17 @@

- - + + - + - + - + <#if emailIsEnabled??>

@@ -57,7 +57,7 @@

- or Cancel + or Cancel From 830456ac9f99d6fd496e0c54ec5f5ad825ade6d7 Mon Sep 17 00:00:00 2001 From: runeliza Date: Wed, 15 Jun 2011 19:00:56 +0000 Subject: [PATCH 30/47] More cleanup. --- .../controller/JSONReconcileServlet.java | 85 +++++-------------- 1 file changed, 22 insertions(+), 63 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java index c3ea6360e..fb863888b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/JSONReconcileServlet.java @@ -15,6 +15,7 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.lucene.analysis.Analyzer; @@ -53,7 +54,8 @@ import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneSetup; */ public class JSONReconcileServlet extends VitroHttpServlet { - private static String QUERY_PARAMETER_NAME = "term"; + private static final long serialVersionUID = 1L; + private static String QUERY_PARAMETER_NAME = "term"; public static final int MAX_QUERY_LENGTH = 500; private static final Log log = LogFactory.getLog(JSONReconcileServlet.class.getName()); @@ -70,14 +72,14 @@ public class JSONReconcileServlet extends VitroHttpServlet { super.doGet(req, resp); resp.setContentType("application/json"); VitroRequest vreq = new VitroRequest(req); -// System.out.println("vreq"); -// System.out.println(vreq.getWebappDaoFactory()); - + //log.debug("vreq"); + //log.debug(vreq.getWebappDaoFactory()); + try { if (vreq.getParameter("query") != null || vreq.getParameter("queries") != null) { JSONObject qJson = getResult(vreq, req, resp); -// System.out.println("result: " + qJson.toString()); + log.debug("result: " + qJson.toString()); String responseStr = (vreq.getParameter("callback") == null) ? qJson .toString() : vreq.getParameter("callback") + "(" + qJson.toString() + ")"; @@ -85,23 +87,14 @@ public class JSONReconcileServlet extends VitroHttpServlet { out.print(responseStr); } else { // metadata String defaultNamespace = null; - //String defaultTypeList = null; + String defaultTypeList = null; String serverName = null; int serverPort = req.getServerPort(); if (vreq.getWebappDaoFactory() != null) { defaultNamespace = vreq.getWebappDaoFactory().getDefaultNamespace(); } - String defaultTypeList = - ConfigurationProperties.getBean(getServletContext()).getProperty("Vitro.reconcile.defaultTypeList"); - - //defaultTypeList = - // "http://vivoweb.org/ontology/core#Course, Course; " + - // "http://vivoweb.org/ontology/core#Grant, Grant; " + - // "http://aims.fao.org/aos/geopolitical.owl, Location; " + - // "http://xmlns.com/foaf/0.1/Organization, Organization; " + - // "http://xmlns.com/foaf/0.1/Person, Person; " + - // "http://purl.org/ontology/bibo/Article, Publication"; + defaultTypeList = ConfigurationProperties.getBean(req).getProperty("Vitro.reconcile.defaultTypeList"); serverName = req.getServerName(); JSONObject metaJson = getMetadata(req, resp, defaultNamespace, defaultTypeList, serverName, serverPort); String callbackStr = (vreq.getParameter("callback") == null) ? "" @@ -133,8 +126,7 @@ public class JSONReconcileServlet extends VitroHttpServlet { // "q2":{"query":"Dina","type":"http://xmlns.com/foaf/0.1/Person","type_strict":"should"}} String qStr = (String) qObj; queries.add(qStr); -// System.out.println(); -// System.out.println("query: " + qStr + "\n"); + log.debug("\nquery: " + qStr + "\n"); } try { @@ -167,7 +159,7 @@ public class JSONReconcileServlet extends VitroHttpServlet { } } } catch (JSONException ex) { - System.err.println("JSONReconcileServlet JSONException: " + ex); + log.error("JSONException: " + ex); throw new ServletException("JSONReconcileServlet JSONException: " + ex); } @@ -302,7 +294,8 @@ public class JSONReconcileServlet extends VitroHttpServlet { Individual ind = iDao.getIndividualByURI(uri); if (ind != null) { String name = ind.getName(); - String modUri = uri.replace("#", "%23"); // encodes # to %23 + // encode # to %23 + String modUri = uri.replace("#", "%23"); resultJson.put("id", modUri); resultJson.put("name", name); } @@ -335,15 +328,15 @@ public class JSONReconcileServlet extends VitroHttpServlet { } } catch (JSONException ex) { - System.err.println("JSONReconcileServlet JSONException: " + ex); + log.error("JSONException: " + ex); throw new ServletException("JSONReconcileServlet JSONException: " + ex); } catch (SearchException ex) { - System.err.println("JSONReconcileServlet SearchException: " + ex); + log.error("SearchException: " + ex); throw new ServletException("JSONReconcileServlet SearchException: " + ex); } catch (IOException ex) { - System.err.println("JSONReconcileServlet IOException: " + ex); + log.error("IOException: " + ex); throw new ServletException("JSONReconcileServlet IOException: " + ex); } @@ -362,30 +355,12 @@ public class JSONReconcileServlet extends VitroHttpServlet { private Query makeReconcileNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) { - /* Original code - String tokenizeParam = (String) request.getParameter("tokenize"); - boolean tokenize = "true".equals(tokenizeParam); - - // Note: Stemming is only relevant if we are tokenizing: an untokenized name - // query will not be stemmed. So we don't look at the stem parameter until we get to - // makeTokenizedNameQuery(). - if (tokenize) { - return makeTokenizedNameQuery(querystr, analyzer, request); - } else { - return makeUntokenizedNameQuery(querystr); - } - */ - - // modified code for reconciliation service - request.setAttribute("stem", true); return makeTokenizedNameQuery(querystr, analyzer, request); } private Query makeTokenizedNameQuery(String querystr, Analyzer analyzer, HttpServletRequest request) { - - String stemParam = (String) request.getParameter("stem"); - boolean stem = "true".equals(stemParam); - String termName = stem ? VitroLuceneTermNames.NAME_STEMMED : VitroLuceneTermNames.NAME_UNSTEMMED; + + String termName = VitroLuceneTermNames.NAME_STEMMED; BooleanQuery boolQuery = new BooleanQuery(); @@ -415,30 +390,16 @@ public class JSONReconcileServlet extends VitroHttpServlet { } catch (ParseException e) { log.warn(e, e); } - - + return boolQuery; } - - private Query makeUntokenizedNameQuery(String querystr) { - - querystr = querystr.toLowerCase(); - String termName = VitroLuceneTermNames.NAME_LOWERCASE; - BooleanQuery query = new BooleanQuery(); - log.debug("Adding wildcard query on unanalyzed name"); - query.add( - new WildcardQuery(new Term(termName, querystr + "*")), - BooleanClause.Occur.MUST); - - return query; - } private QueryParser getQueryParser(String searchField, Analyzer analyzer){ // searchField indicates which field to search against when there is no term // indicated in the query string. // The analyzer is needed so that we use the same analyzer on the search queries as // was used on the text that was indexed. - QueryParser qp = new QueryParser(searchField,analyzer); + QueryParser qp = new QueryParser(Version.LUCENE_29, searchField,analyzer); //this sets the query parser to AND all of the query terms it finds. qp.setDefaultOperator(QueryParser.AND_OPERATOR); return qp; @@ -458,10 +419,8 @@ public class JSONReconcileServlet extends VitroHttpServlet { "query length is " + MAX_QUERY_LENGTH ); return null; } - - + query = makeReconcileNameQuery(querystr, analyzer, request); - // filter by type if (typeParam != null) { @@ -479,7 +438,7 @@ public class JSONReconcileServlet extends VitroHttpServlet { while (it.hasNext()) { String[] pvPair = it.next(); Query extraQuery = makeReconcileNameQuery(pvPair[1], analyzer, request); - if (!"".equals(pvPair[0]) && pvPair[0] != null) { + if ( ! StringUtils.isEmpty(pvPair[0]) ) { BooleanQuery boolQuery = new BooleanQuery(); boolQuery.add(new TermQuery(new Term( VitroLuceneTermNames.RDFTYPE, pvPair[0])), From 6af401dd6f5c8aa89cb6e53b7b6f4a31ca8d517d Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 15 Jun 2011 19:23:27 +0000 Subject: [PATCH 31/47] root user must also get the privileged timeout interval. --- .../webapp/controller/authenticate/BasicAuthenticator.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java index f84bf041b..ca0cfdf3b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java @@ -125,7 +125,7 @@ public class BasicAuthenticator extends Authenticator { HttpSession session = request.getSession(); createLoginStatusBean(userAccount.getUri(), authSource, session); - setSessionTimeoutLimit(session); + setSessionTimeoutLimit(userAccount, session); recordInUserSessionMap(userAccount.getUri(), session); notifyOtherUsers(userAccount.getUri(), session); } @@ -151,11 +151,14 @@ public class BasicAuthenticator extends Authenticator { /** * Editors and other privileged users get a longer timeout interval. */ - private void setSessionTimeoutLimit(HttpSession session) { + private void setSessionTimeoutLimit(UserAccount userAccount, + HttpSession session) { RoleLevel role = RoleLevel.getRoleFromLoginStatus(request); if (role == RoleLevel.EDITOR || role == RoleLevel.CURATOR || role == RoleLevel.DB_ADMIN) { session.setMaxInactiveInterval(PRIVILEGED_TIMEOUT_INTERVAL); + } else if (getUserAccountsDao().isRootUser(userAccount)) { + session.setMaxInactiveInterval(PRIVILEGED_TIMEOUT_INTERVAL); } else { session.setMaxInactiveInterval(LOGGED_IN_TIMEOUT_INTERVAL); } From 2bfb79995e461146e0590bbd0588e62fc4f8eb58 Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 15 Jun 2011 19:51:46 +0000 Subject: [PATCH 32/47] Add External Authorization ID to the "Add Account" and "Edit Account" pages. --- .../accounts/admin/UserAccountsAddPage.java | 18 +++++++++++++++-- .../accounts/admin/UserAccountsEditPage.java | 20 +++++++++++++++++++ .../body/accounts/userAccounts-add.ftl | 7 +++++++ .../body/accounts/userAccounts-edit.ftl | 7 +++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java index 51c723459..2add74003 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPage.java @@ -22,6 +22,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem public class UserAccountsAddPage extends UserAccountsPage { private static final String PARAMETER_SUBMIT = "submitAdd"; private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress"; + private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId"; private static final String PARAMETER_FIRST_NAME = "firstName"; private static final String PARAMETER_LAST_NAME = "lastName"; private static final String PARAMETER_ROLE = "role"; @@ -30,6 +31,7 @@ public class UserAccountsAddPage extends UserAccountsPage { private static final String ERROR_NO_EMAIL = "errorEmailIsEmpty"; private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse"; private static final String ERROR_EMAIL_INVALID_FORMAT = "errorEmailInvalidFormat"; + private static final String ERROR_EXTERNAL_AUTH_ID_IN_USE = "errorExternalAuthIdInUse"; private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty"; private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty"; private static final String ERROR_NO_ROLE = "errorNoRoleSelected"; @@ -41,6 +43,7 @@ public class UserAccountsAddPage extends UserAccountsPage { /* The request parameters */ private boolean submit; private String emailAddress = ""; + private String externalAuthId = ""; private String firstName = ""; private String lastName = ""; private String selectedRoleUri = ""; @@ -68,6 +71,7 @@ public class UserAccountsAddPage extends UserAccountsPage { private void parseRequestParameters() { submit = isFlagOnRequest(PARAMETER_SUBMIT); emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, ""); + externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, ""); firstName = getStringParameter(PARAMETER_FIRST_NAME, ""); lastName = getStringParameter(PARAMETER_LAST_NAME, ""); selectedRoleUri = getStringParameter(PARAMETER_ROLE, ""); @@ -88,6 +92,8 @@ public class UserAccountsAddPage extends UserAccountsPage { errorCode = ERROR_EMAIL_IN_USE; } else if (!isEmailValidFormat()) { errorCode = ERROR_EMAIL_INVALID_FORMAT; + } else if (isExternalAuthIdInUse()) { + errorCode = ERROR_EXTERNAL_AUTH_ID_IN_USE; } else if (firstName.isEmpty()) { errorCode = ERROR_NO_FIRST_NAME; } else if (lastName.isEmpty()) { @@ -103,10 +109,17 @@ public class UserAccountsAddPage extends UserAccountsPage { return userAccountsDao.getUserAccountByEmail(emailAddress) != null; } + private boolean isExternalAuthIdInUse() { + if (externalAuthId.isEmpty()) { + return false; + } + return userAccountsDao.getUserAccountByExternalAuthId(externalAuthId) != null; + } + private boolean isEmailValidFormat() { return Authenticator.isValidEmailAddress(emailAddress); } - + public boolean isValid() { return errorCode.isEmpty(); } @@ -116,7 +129,7 @@ public class UserAccountsAddPage extends UserAccountsPage { u.setEmailAddress(emailAddress); u.setFirstName(firstName); u.setLastName(lastName); - u.setExternalAuthId(""); + u.setExternalAuthId(externalAuthId); u.setMd5Password(""); u.setOldPassword(""); @@ -139,6 +152,7 @@ public class UserAccountsAddPage extends UserAccountsPage { Map body = new HashMap(); body.put("emailAddress", emailAddress); + body.put("externalAuthId", externalAuthId); body.put("firstName", firstName); body.put("lastName", lastName); body.put("selectedRole", selectedRoleUri); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java index c939dfe24..b53b008ca 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java @@ -28,6 +28,7 @@ public class UserAccountsEditPage extends UserAccountsPage { private static final String PARAMETER_SUBMIT = "submitEdit"; private static final String PARAMETER_USER_URI = "editAccount"; private static final String PARAMETER_EMAIL_ADDRESS = "emailAddress"; + private static final String PARAMETER_EXTERNAL_AUTH_ID = "externalAuthId"; private static final String PARAMETER_FIRST_NAME = "firstName"; private static final String PARAMETER_LAST_NAME = "lastName"; private static final String PARAMETER_ROLE = "role"; @@ -36,6 +37,7 @@ public class UserAccountsEditPage extends UserAccountsPage { private static final String ERROR_NO_EMAIL = "errorEmailIsEmpty"; private static final String ERROR_EMAIL_IN_USE = "errorEmailInUse"; private static final String ERROR_EMAIL_INVALID_FORMAT = "errorEmailInvalidFormat"; + private static final String ERROR_EXTERNAL_AUTH_ID_IN_USE = "errorExternalAuthIdInUse"; private static final String ERROR_NO_FIRST_NAME = "errorFirstNameIsEmpty"; private static final String ERROR_NO_LAST_NAME = "errorLastNameIsEmpty"; private static final String ERROR_NO_ROLE = "errorNoRoleSelected"; @@ -48,6 +50,7 @@ public class UserAccountsEditPage extends UserAccountsPage { private boolean submit; private String userUri = ""; private String emailAddress = ""; + private String externalAuthId = ""; private String firstName = ""; private String lastName = ""; private String selectedRoleUri = ""; @@ -79,6 +82,7 @@ public class UserAccountsEditPage extends UserAccountsPage { submit = isFlagOnRequest(PARAMETER_SUBMIT); userUri = getStringParameter(PARAMETER_USER_URI, ""); emailAddress = getStringParameter(PARAMETER_EMAIL_ADDRESS, ""); + externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, ""); firstName = getStringParameter(PARAMETER_FIRST_NAME, ""); lastName = getStringParameter(PARAMETER_LAST_NAME, ""); selectedRoleUri = getStringParameter(PARAMETER_ROLE, ""); @@ -117,6 +121,8 @@ public class UserAccountsEditPage extends UserAccountsPage { errorCode = ERROR_EMAIL_IN_USE; } else if (!isEmailValidFormat()) { errorCode = ERROR_EMAIL_INVALID_FORMAT; + } else if (externalAuthIdIsChanged() && isExternalAuthIdInUse()) { + errorCode = ERROR_EXTERNAL_AUTH_ID_IN_USE; } else if (firstName.isEmpty()) { errorCode = ERROR_NO_FIRST_NAME; } else if (lastName.isEmpty()) { @@ -140,6 +146,17 @@ public class UserAccountsEditPage extends UserAccountsPage { return Authenticator.isValidEmailAddress(emailAddress); } + private boolean externalAuthIdIsChanged() { + return !externalAuthId.equals(userAccount.getExternalAuthId()); + } + + private boolean isExternalAuthIdInUse() { + if (externalAuthId.isEmpty()) { + return false; + } + return userAccountsDao.getUserAccountByExternalAuthId(externalAuthId) != null; + } + public boolean isValid() { return errorCode.isEmpty(); } @@ -149,11 +166,13 @@ public class UserAccountsEditPage extends UserAccountsPage { if (isSubmit()) { body.put("emailAddress", emailAddress); + body.put("externalAuthId", externalAuthId); body.put("firstName", firstName); body.put("lastName", lastName); body.put("selectedRole", selectedRoleUri); } else { body.put("emailAddress", userAccount.getEmailAddress()); + body.put("externalAuthId", userAccount.getExternalAuthId()); body.put("firstName", userAccount.getFirstName()); body.put("lastName", userAccount.getLastName()); body.put("selectedRole", getExistingRoleUri()); @@ -192,6 +211,7 @@ public class UserAccountsEditPage extends UserAccountsPage { userAccount.setEmailAddress(emailAddress); userAccount.setFirstName(firstName); userAccount.setLastName(lastName); + userAccount.setExternalAuthId(externalAuthId); userAccount .setPermissionSetUris(Collections.singleton(selectedRoleUri)); diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl index c6d4809c6..5106ca8d8 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl @@ -16,6 +16,10 @@ <#assign errorMessage = "'${emailAddress}' is not a valid email address." /> + <#if errorExternalAuthIdInUse??> + <#assign errorMessage = "An account with that external authorization ID already exists." /> + + <#if errorFirstNameIsEmpty??> <#assign errorMessage = "You must supply a first name." /> @@ -61,6 +65,9 @@ + + +

Roles *

<#list roles as role> selected /> diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl index 0d9e30718..816a6306a 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl @@ -16,6 +16,10 @@ <#assign errorMessage = "'${emailAddress}' is not a valid email address." /> + <#if errorExternalAuthIdInUse??> + <#assign errorMessage = "An account with that external authorization ID already exists." /> + + <#if errorFirstNameIsEmpty??> <#assign errorMessage = "You must supply a first name." /> @@ -61,6 +65,9 @@ + + +

Roles *

<#list roles as role> selected /> From 8e94e7a4e30929ebb8859a65ff48c390ec8cb80c Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 15 Jun 2011 20:10:01 +0000 Subject: [PATCH 33/47] NIHVIVO-2705 correct the selection of existing roles. --- .../web/templates/freemarker/body/accounts/userAccounts-add.ftl | 2 +- .../templates/freemarker/body/accounts/userAccounts-edit.ftl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl index 5106ca8d8..5013f2bfa 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-add.ftl @@ -70,7 +70,7 @@

Roles *

<#list roles as role> - selected /> + checked />
diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl index 816a6306a..2e5ae7a48 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl @@ -70,7 +70,7 @@

Roles *

<#list roles as role> - selected /> + checked />
From 6f4a02451063adb2e2c76590b8c27432956d9508 Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 15 Jun 2011 20:41:44 +0000 Subject: [PATCH 34/47] NIHVIVO-2703 Root user shouldn't require a role, and shouldn't accept one if offered. --- .../accounts/admin/UserAccountsEditPage.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java index b53b008ca..8f9d261d1 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPage.java @@ -85,7 +85,7 @@ public class UserAccountsEditPage extends UserAccountsPage { externalAuthId = getStringParameter(PARAMETER_EXTERNAL_AUTH_ID, ""); firstName = getStringParameter(PARAMETER_FIRST_NAME, ""); lastName = getStringParameter(PARAMETER_LAST_NAME, ""); - selectedRoleUri = getStringParameter(PARAMETER_ROLE, ""); + selectedRoleUri = isRootUser() ? "" :getStringParameter(PARAMETER_ROLE, ""); associateWithProfile = isParameterAsExpected( PARAMETER_ASSOCIATE_WITH_PROFILE, "yes"); @@ -127,7 +127,7 @@ public class UserAccountsEditPage extends UserAccountsPage { errorCode = ERROR_NO_FIRST_NAME; } else if (lastName.isEmpty()) { errorCode = ERROR_NO_LAST_NAME; - } else if (selectedRoleUri.isEmpty()) { + } else if (!isRootUser() && selectedRoleUri.isEmpty()) { errorCode = ERROR_NO_ROLE; } else { errorCode = strategy.additionalValidations(); @@ -145,7 +145,7 @@ public class UserAccountsEditPage extends UserAccountsPage { private boolean isEmailValidFormat() { return Authenticator.isValidEmailAddress(emailAddress); } - + private boolean externalAuthIdIsChanged() { return !externalAuthId.equals(userAccount.getExternalAuthId()); } @@ -157,6 +157,10 @@ public class UserAccountsEditPage extends UserAccountsPage { return userAccountsDao.getUserAccountByExternalAuthId(externalAuthId) != null; } + private boolean isRootUser() { + return userAccountsDao.isRootUser(userAccount); + } + public boolean isValid() { return errorCode.isEmpty(); } @@ -177,6 +181,11 @@ public class UserAccountsEditPage extends UserAccountsPage { body.put("lastName", userAccount.getLastName()); body.put("selectedRole", getExistingRoleUri()); } + + if (isRootUser()) { + body.put("selectedRole", ""); + } + body.put("roles", buildRolesList()); if (associateWithProfile) { body.put("associate", Boolean.TRUE); @@ -213,8 +222,12 @@ public class UserAccountsEditPage extends UserAccountsPage { userAccount.setLastName(lastName); userAccount.setExternalAuthId(externalAuthId); - userAccount - .setPermissionSetUris(Collections.singleton(selectedRoleUri)); + if (isRootUser()) { + userAccount.setPermissionSetUris(Collections. emptySet()); + } else { + userAccount.setPermissionSetUris(Collections + .singleton(selectedRoleUri)); + } strategy.setAdditionalProperties(userAccount); From cd099505a641386749567523713bf9ccdbbfd181 Mon Sep 17 00:00:00 2001 From: j2blake Date: Wed, 15 Jun 2011 20:50:31 +0000 Subject: [PATCH 35/47] NIHVIVO-2706 "Reset password" box remains checked if the form is presented again. --- .../templates/freemarker/body/accounts/userAccounts-edit.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl index 2e5ae7a48..5c0e2689a 100644 --- a/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl +++ b/webapp/web/templates/freemarker/body/accounts/userAccounts-edit.ftl @@ -94,7 +94,7 @@
- + checked /> <#if emailIsEnabled??> From 1ffe229a304322b406e1f2b2840fd9ea71a42686 Mon Sep 17 00:00:00 2001 From: j2blake Date: Thu, 16 Jun 2011 13:57:11 +0000 Subject: [PATCH 36/47] NIHVIVO-2690 Root user should not receive the "no profile" message. --- .../webapp/controller/authenticate/Authenticator.java | 5 +++-- .../controller/authenticate/BasicAuthenticator.java | 2 ++ .../controller/authenticate/LoginRedirector.java | 11 ++++++++++- .../webapp/controller/edit/AuthenticateTest.java | 5 +++++ .../mannlib/vitro/webapp/dao/UserAccountsDaoStub.java | 11 ++++++----- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java index 45b676164..db7036c6e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java @@ -96,8 +96,9 @@ public abstract class Authenticator { *
 	 * Record that the user has logged in, with all of the housekeeping that 
 	 * goes with it:
-	 * - updating the user record
-	 * - setting login status and timeout limit in the session
+	 * - update the user record
+	 * - set login status and timeout limit in the session
+	 * - refresh the Identifiers on the request
 	 * - record the user in the session map
 	 * - notify other users of the model
 	 * 
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java index ca0cfdf3b..cd4a3f366 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java @@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vedit.beans.LoginStatusBean; import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers; import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.SelfEditingConfiguration; @@ -125,6 +126,7 @@ public class BasicAuthenticator extends Authenticator { HttpSession session = request.getSession(); createLoginStatusBean(userAccount.getUri(), authSource, session); + RequestIdentifiers.resetIdentifiers(request); setSessionTimeoutLimit(userAccount, session); recordInUserSessionMap(userAccount.getUri(), session); notifyOtherUsers(userAccount.getUri(), session); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java index f25db5be9..ede8e4101 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java @@ -16,6 +16,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vedit.beans.LoginStatusBean; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.HasRoleLevel; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.IsRootUser; import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel; import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; @@ -152,7 +156,12 @@ public class LoginRedirector { } private boolean isMerelySelfEditor() { - RoleLevel role = RoleLevel.getRoleFromLoginStatus(request); + IdentifierBundle ids = RequestIdentifiers.getIdBundleForRequest(request); + if (IsRootUser.isRootUser(ids)) { + return false; + } + + RoleLevel role = HasRoleLevel.getUsersRoleLevel(ids); return role == RoleLevel.PUBLIC || role == RoleLevel.SELF; } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java index 80042b241..f186140ad 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java @@ -32,6 +32,8 @@ import stubs.javax.servlet.http.HttpSessionStub; import edu.cornell.mannlib.vedit.beans.LoginStatusBean; import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; import edu.cornell.mannlib.vitro.testing.AbstractTestClass; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.ActiveIdentifierBundleFactories; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.CommonIdentifierBundleFactory; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator; import edu.cornell.mannlib.vitro.webapp.controller.authenticate.AuthenticatorStub; @@ -143,6 +145,9 @@ public class AuthenticateTest extends AbstractTestClass { auth = new Authenticate(); auth.init(servletConfig); + + ActiveIdentifierBundleFactories.addFactory(servletContext, + new CommonIdentifierBundleFactory(servletContext)); } private UserAccount createUserFromUserInfo(UserInfo userInfo) { diff --git a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDaoStub.java b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDaoStub.java index c0a96befe..2665db61d 100644 --- a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDaoStub.java +++ b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDaoStub.java @@ -38,6 +38,12 @@ public class UserAccountsDaoStub implements UserAccountsDao { return userAccountsByUri.get(uri); } + @Override + public boolean isRootUser(UserAccount userAccount) { + // TODO for now, no user is Root + return false; + } + // ---------------------------------------------------------------------- // Un-implemented methods // ---------------------------------------------------------------------- @@ -48,11 +54,6 @@ public class UserAccountsDaoStub implements UserAccountsDao { "UserAccountsDaoStub.getUserAccountByEmail() not implemented."); } - @Override - public boolean isRootUser(UserAccount userAccount) { - throw new RuntimeException("UserAccountsDao.isRootUser() not implemented."); - } - @Override public String insertUserAccount(UserAccount userAccount) { throw new RuntimeException( From 66dea2ff6cd2bef17031eee57f6a7a8e3d79bb6d Mon Sep 17 00:00:00 2001 From: tworrall Date: Thu, 16 Jun 2011 14:37:33 +0000 Subject: [PATCH 37/47] NIHVIVO-2710: changed span to heading --- webapp/web/css/vitro.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webapp/web/css/vitro.css b/webapp/web/css/vitro.css index 8452671b3..7ec39d5dd 100644 --- a/webapp/web/css/vitro.css +++ b/webapp/web/css/vitro.css @@ -87,8 +87,9 @@ color: #fff; background: #5e6363; } -.searchTOC span { +.searchTOC h4 { color: #fff; + padding: 0 0 0 0; } .searchTOC ul { width: 160px; From fcd877b5e29d69adbb493303186f5b9f00ef2ad1 Mon Sep 17 00:00:00 2001 From: tworrall Date: Thu, 16 Jun 2011 14:38:00 +0000 Subject: [PATCH 38/47] NIHVIVO-2710: changed span to heading --- .../templates/freemarker/body/search/search-pagedResults.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl b/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl index 8030d496b..f58fb4d89 100644 --- a/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl +++ b/webapp/web/templates/freemarker/body/search/search-pagedResults.ftl @@ -13,7 +13,7 @@ <#-- Refinement links --> <#if classGroupLinks?has_content>
- Display only +

Display only

    <#list classGroupLinks as link>
  • ${link.text}
  • @@ -24,7 +24,7 @@ <#if classLinks?has_content>
    - Limit ${classGroupName} to +

    Limit ${classGroupName} to

      <#list classLinks as link>
    • ${link.text}
    • From be3851b15e84b520654945a8760604695b60d2c3 Mon Sep 17 00:00:00 2001 From: tworrall Date: Thu, 16 Jun 2011 14:40:39 +0000 Subject: [PATCH 39/47] NIHVIVO-2483: moved subclass heading above a-z navigation --- webapp/web/css/menupage/menupage.css | 13 +++++++++---- webapp/web/js/menupage/browseByVClass.js | 5 +++-- .../body/partials/menupage/menupage-browse.ftl | 3 ++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/webapp/web/css/menupage/menupage.css b/webapp/web/css/menupage/menupage.css index 38dd1fb4b..cf61e2bab 100644 --- a/webapp/web/css/menupage/menupage.css +++ b/webapp/web/css/menupage/menupage.css @@ -193,14 +193,14 @@ ul#browse-classes a { ul#alpha-browse-individuals { float: left; width: 619px; - padding-left: 10px; - list-style: none; - margin-left: 1px; + /* padding-left: 10px; */ + list-style: none; + /* margin-left: 1px; */ } ul#alpha-browse-individuals li { float: left; margin-right: 4px; - padding-top: 8px; + padding-top: 0px; } ul#alpha-browse-individuals li:last-child { border-bottom: 0; @@ -212,6 +212,11 @@ ul#alpha-browse-individuals a { padding-left: 8px; width: 10px; } +h4#selectedClassHeading { + margin-left:4px; + margin-top:-5px; + margin-bottom:-10px; +} /* BROWSE INDIVIDUALS------> */ #individuals-in-class { float: right; diff --git a/webapp/web/js/menupage/browseByVClass.js b/webapp/web/js/menupage/browseByVClass.js index 712c46e22..ef28d5f74 100644 --- a/webapp/web/js/menupage/browseByVClass.js +++ b/webapp/web/js/menupage/browseByVClass.js @@ -140,8 +140,9 @@ var browseByVClass = { browseByVClass.pagination(pages, page); } - selectedClassHeading = '

      '+ results.vclass.name +'

      '; - browseByVClass.individualsContainer.prepend(selectedClassHeading); + // selectedClassHeading = '

      '+ results.vclass.name +'

      '; NIHVIVO-2483 tlw72 + // browseByVClass.individualsContainer.prepend(selectedClassHeading); + $('h4#selectedClassHeading').text(results.vclass.name); // NIHVIVO-2483 tlw72 // Set selected class, alpha and page browseByVClass.selectedVClass(results.vclass.URI); diff --git a/webapp/web/templates/freemarker/body/partials/menupage/menupage-browse.ftl b/webapp/web/templates/freemarker/body/partials/menupage/menupage-browse.ftl index 212361a99..afaf93e09 100644 --- a/webapp/web/templates/freemarker/body/partials/menupage/menupage-browse.ftl +++ b/webapp/web/templates/freemarker/body/partials/menupage/menupage-browse.ftl @@ -20,7 +20,8 @@
    -

> Add new account