");
- 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/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..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() + ")";
@@ -124,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 {
@@ -158,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);
}
@@ -327,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);
}
@@ -354,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();
@@ -407,23 +390,9 @@ 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
@@ -450,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) {
@@ -471,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])),
@@ -489,3 +456,4 @@ public class JSONReconcileServlet extends VitroHttpServlet {
}
}
+
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java
index 9c4c51cb1..315f8408a 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java
@@ -39,7 +39,7 @@ public class UserAccountsSelector {
+ "PREFIX fn: \n"
+ "PREFIX auth: \n";
- private static final String ALL_VARIABLES = "?uri ?email ?firstName ?lastName ?pwd ?expire ?count ?status";
+ private static final String ALL_VARIABLES = "?uri ?email ?firstName ?lastName ?pwd ?expire ?count ?status ?isRoot";
private static final String COUNT_VARIABLE = "?uri";
@@ -169,7 +169,8 @@ public class UserAccountsSelector {
+ " OPTIONAL { ?uri auth:md5password ?pwd } \n"
+ " OPTIONAL { ?uri auth:passwordChangeExpires ?expire } \n"
+ " OPTIONAL { ?uri auth:loginCount ?count } \n"
- + " OPTIONAL { ?uri auth:status ?status }";
+ + " OPTIONAL { ?uri auth:status ?status } \n"
+ + " OPTIONAL { ?uri ?isRoot auth:RootUserAccount }";
}
private String filterClauses() {
@@ -201,11 +202,10 @@ public class UserAccountsSelector {
}
/**
- * Escape any regex special characters in the string.
+ * Escape any regex special characters in the string.
*
- * Note that the SPARQL
- * parser requires two backslashes, in order to pass a single backslash to
- * the REGEX function.
+ * Note that the SPARQL parser requires two backslashes, in order to pass a
+ * single backslash to the REGEX function.
*/
private String escapeForRegex(String raw) {
StringBuilder clean = new StringBuilder();
@@ -327,6 +327,7 @@ public class UserAccountsSelector {
user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L));
user.setLoginCount(ifIntPresent(solution, "count", 0));
user.setStatus(parseStatus(solution, "status", null));
+ user.setRootUser(solution.contains("isRoot"));
return user;
}
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/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/UserAccountsAdminController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAdminController.java
index b17a01c32..f21d4c340 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAdminController.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAdminController.java
@@ -57,9 +57,9 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
if (page.isSubmit() && page.isValid()) {
page.createNewAccount();
- UserAccountsListPage listPage = new UserAccountsListPage(vreq);
- return listPage.showPageWithNewAccount(page.getAddedAccount(),
- page.wasPasswordEmailSent());
+ UserAccountsListPage.Message.showNewAccount(vreq,
+ page.getAddedAccount(), page.wasPasswordEmailSent());
+ return redirectToList();
} else {
return page.showPage();
}
@@ -71,9 +71,10 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
return showHomePage(vreq, page.getBogusMessage());
} else if (page.isSubmit() && page.isValid()) {
page.updateAccount();
- UserAccountsListPage listPage = new UserAccountsListPage(vreq);
- return listPage.showPageWithUpdatedAccount(
+
+ UserAccountsListPage.Message.showUpdatedAccount(vreq,
page.getUpdatedAccount(), page.wasPasswordEmailSent());
+ return redirectToList();
} else {
return page.showPage();
}
@@ -83,8 +84,8 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
UserAccountsDeleter deleter = new UserAccountsDeleter(vreq);
Collection deletedUris = deleter.delete();
- return new UserAccountsListPage(vreq)
- .showPageWithDeletions(deletedUris);
+ UserAccountsListPage.Message.showDeletions(vreq, deletedUris);
+ return redirectToList();
}
private ResponseValues handleListRequest(VitroRequest vreq) {
@@ -92,6 +93,14 @@ public class UserAccountsAdminController extends FreemarkerHttpServlet {
return page.showPage();
}
+ /**
+ * After an successful change, redirect to the list instead of forwarding.
+ * That way, a browser "refresh" won't try to repeat the operation.
+ */
+ private ResponseValues redirectToList() {
+ return new RedirectResponseValues("/accountsAdmin/list");
+ }
+
private ResponseValues showHomePage(VitroRequest vreq, String message) {
DisplayMessage.setMessage(vreq, message);
return new RedirectResponseValues("/");
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..8b88daf94 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,11 +121,13 @@ 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()) {
errorCode = ERROR_NO_LAST_NAME;
- } else if (selectedRoleUri.isEmpty()) {
+ } else if (!isRootUser() && selectedRoleUri.isEmpty()) {
errorCode = ERROR_NO_ROLE;
} else {
errorCode = strategy.additionalValidations();
@@ -139,7 +145,22 @@ public class UserAccountsEditPage extends UserAccountsPage {
private boolean isEmailValidFormat() {
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;
+ }
+
+ private boolean isRootUser() {
+ return ((userAccount != null) && userAccount.isRootUser());
+ }
+
public boolean isValid() {
return errorCode.isEmpty();
}
@@ -149,16 +170,22 @@ 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());
}
- body.put("roles", buildRolesList());
+
+ if (!isRootUser()) {
+ body.put("roles", buildRolesList());
+ }
+
if (associateWithProfile) {
body.put("associate", Boolean.TRUE);
}
@@ -192,9 +219,14 @@ public class UserAccountsEditPage extends UserAccountsPage {
userAccount.setEmailAddress(emailAddress);
userAccount.setFirstName(firstName);
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);
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..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
@@ -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;
@@ -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;
@@ -102,19 +103,23 @@ 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.setSubject("Reset password request");
- email.setHtmlTemplate("userAccounts-resetPasswordEmail-html.ftl");
- email.setTextTemplate("userAccounts-resetPasswordEmail-text.ftl");
+ email.setTemplate(EMAIL_TEMPLATE);
email.setBodyMap(body);
+ email.processTemplate();
email.send();
sentEmail = true;
}
+
+ private String getSiteName() {
+ ApplicationBean appBean = vreq.getAppBean();
+ return appBean.getApplicationName();
+ }
private String buildResetPasswordLink() {
try {
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsListPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsListPage.java
index 08476691d..3da82e412 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsListPage.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsListPage.java
@@ -11,6 +11,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -19,12 +22,12 @@ 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.UserAccountsOrdering;
+import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction;
+import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsPage;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelection;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelectionCriteria;
import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsSelector;
-import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Direction;
-import edu.cornell.mannlib.vitro.webapp.controller.accounts.UserAccountsOrdering.Field;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
@@ -91,55 +94,7 @@ public class UserAccountsListPage extends UserAccountsPage {
UserAccountsSelection selection = UserAccountsSelector.select(
userAccountsModel, criteria);
Map body = buildTemplateBodyMap(selection);
- return new TemplateResponseValues(TEMPLATE_NAME, body);
- }
-
- /**
- * We just came from adding a new account. Show the list with a message.
- */
- public ResponseValues showPageWithNewAccount(UserAccount userAccount,
- boolean emailWasSent) {
- UserAccountsSelection selection = UserAccountsSelector.select(
- userAccountsModel, criteria);
- Map body = buildTemplateBodyMap(selection);
-
- body.put("newUserAccount", new UserAccountWrapper(userAccount,
- Collections. emptyList()));
- if (emailWasSent) {
- body.put("emailWasSent", Boolean.TRUE);
- }
-
- return new TemplateResponseValues(TEMPLATE_NAME, body);
- }
-
- /**
- * We just came from editing an account. Show the list with a message.
- */
- public ResponseValues showPageWithUpdatedAccount(UserAccount userAccount,
- boolean emailWasSent) {
- UserAccountsSelection selection = UserAccountsSelector.select(
- userAccountsModel, criteria);
- Map body = buildTemplateBodyMap(selection);
-
- body.put("updatedUserAccount", new UserAccountWrapper(userAccount,
- Collections. emptyList()));
- if (emailWasSent) {
- body.put("emailWasSent", Boolean.TRUE);
- }
-
- return new TemplateResponseValues(TEMPLATE_NAME, body);
- }
-
- /**
- * We just came from deleting accounts. Show the list with a message.
- */
- public ResponseValues showPageWithDeletions(Collection deletedUris) {
- UserAccountsSelection selection = UserAccountsSelector.select(
- userAccountsModel, criteria);
- Map body = buildTemplateBodyMap(selection);
-
- body.put("deletedAccountCount", deletedUris.size());
-
+ Message.applyToBodyMap(vreq, body);
return new TemplateResponseValues(TEMPLATE_NAME, body);
}
@@ -238,10 +193,15 @@ public class UserAccountsListPage extends UserAccountsPage {
private List findPermissionSetLabels(UserAccount account) {
List labels = new ArrayList();
- for (String uri : account.getPermissionSetUris()) {
- PermissionSet pSet = userAccountsDao.getPermissionSetByUri(uri);
- if (pSet != null) {
- labels.add(pSet.getLabel());
+
+ if (account.isRootUser()) {
+ labels.add("ROOT");
+ } else {
+ for (String uri : account.getPermissionSetUris()) {
+ PermissionSet pSet = userAccountsDao.getPermissionSetByUri(uri);
+ if (pSet != null) {
+ labels.add(pSet.getLabel());
+ }
}
}
return labels;
@@ -301,4 +261,84 @@ public class UserAccountsListPage extends UserAccountsPage {
}
+ /**
+ * Message info that lives in the session. Another request can store this,
+ * and it will be displayed (once) by the list page.
+ */
+ public static class Message {
+ private static final String ATTRIBUTE = Message.class.getName();
+ private static final Collection EMPTY = Collections.emptySet();
+
+ public static void showNewAccount(HttpServletRequest req,
+ UserAccount userAccount, boolean emailWasSent) {
+ Message message = new Message(Type.NEW_ACCOUNT, userAccount,
+ emailWasSent, EMPTY);
+ setMessage(req, message);
+ }
+
+ public static void showUpdatedAccount(HttpServletRequest req,
+ UserAccount userAccount, boolean emailWasSent) {
+ Message message = new Message(Type.UPDATED_ACCOUNT, userAccount,
+ emailWasSent, EMPTY);
+ setMessage(req, message);
+ }
+
+ public static void showDeletions(HttpServletRequest req,
+ Collection deletedUris) {
+ Message message = new Message(Type.DELETIONS, null, false,
+ deletedUris);
+ setMessage(req, message);
+ }
+
+ private static void setMessage(HttpServletRequest req, Message message) {
+ req.getSession().setAttribute(ATTRIBUTE, message);
+ }
+
+ public static void applyToBodyMap(HttpServletRequest req,
+ Map body) {
+ HttpSession session = req.getSession();
+ Object o = session.getAttribute(ATTRIBUTE);
+ session.removeAttribute(ATTRIBUTE);
+
+ if (o instanceof Message) {
+ ((Message) o).applyToBodyMap(body);
+ }
+ }
+
+ enum Type {
+ NEW_ACCOUNT, UPDATED_ACCOUNT, DELETIONS
+ }
+
+ private final Type type;
+ private final UserAccount userAccount;
+ private final boolean emailWasSent;
+ private final Collection deletedUris;
+
+ public Message(Type type, UserAccount userAccount,
+ boolean emailWasSent, Collection deletedUris) {
+ this.type = type;
+ this.userAccount = userAccount;
+ this.emailWasSent = emailWasSent;
+ this.deletedUris = deletedUris;
+ }
+
+ private void applyToBodyMap(Map body) {
+ if (type == Type.NEW_ACCOUNT) {
+ body.put("newUserAccount", new UserAccountWrapper(userAccount,
+ Collections. emptyList()));
+ if (emailWasSent) {
+ body.put("emailWasSent", Boolean.TRUE);
+ }
+ } else if (type == Type.UPDATED_ACCOUNT) {
+ body.put("updatedUserAccount", new UserAccountWrapper(
+ userAccount, Collections. emptyList()));
+ if (emailWasSent) {
+ body.put("emailWasSent", Boolean.TRUE);
+ }
+ } else {
+ body.put("deletedAccountCount", deletedUris.size());
+ }
+ }
+ }
+
}
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/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/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/controller/accounts/user/UserAccountsUserController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsUserController.java
index 7628362ac..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);
+ 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..dce2bf46a 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
@@ -51,10 +51,10 @@ public abstract class Authenticator {
// ----------------------------------------------------------------------
/** Maximum inactive interval for a ordinary logged-in session, in seconds. */
- public static final int LOGGED_IN_TIMEOUT_INTERVAL = 300;
+ public static final int LOGGED_IN_TIMEOUT_INTERVAL = 60 * 60;
/** Maximum inactive interval for a editor (or better) session, in seconds. */
- public static final int PRIVILEGED_TIMEOUT_INTERVAL = 32000;
+ public static final int PRIVILEGED_TIMEOUT_INTERVAL = 60 * 60 * 8;
/**
* Get the UserAccount for this external ID, or null if there is none.
@@ -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
*
@@ -105,17 +106,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..6ebb7a4fd 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;
@@ -16,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;
@@ -123,24 +123,13 @@ 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);
- setSessionTimeoutLimit(session);
- recordInUserSessionMap(userUri, session);
- notifyOtherUsers(userUri, session);
+ createLoginStatusBean(userAccount.getUri(), authSource, session);
+ RequestIdentifiers.resetIdentifiers(request);
+ setSessionTimeoutLimit(userAccount, session);
+ recordInUserSessionMap(userAccount.getUri(), session);
+ notifyOtherUsers(userAccount.getUri(), session);
}
/**
@@ -164,11 +153,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 (userAccount.isRootUser()) {
+ session.setMaxInactiveInterval(PRIVILEGED_TIMEOUT_INTERVAL);
} else {
session.setMaxInactiveInterval(LOGGED_IN_TIMEOUT_INTERVAL);
}
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..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,9 @@ 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;
/**
* Handle the return from the external authorization login server. If we are
@@ -36,6 +38,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
@@ -50,39 +59,30 @@ public class LoginExternalAuthReturn extends BaseLoginServlet {
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);
- removeLoginProcessArtifacts(req);
- new LoginRedirector(req).redirectLoggedInUser(resp);
+ 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);
- removeLoginProcessArtifacts(req);
- new LoginRedirector(req).redirectLoggedInUser(resp);
- return;
- }
-
- log.debug("User is not recognized: " + externalAuthId);
- removeLoginProcessArtifacts(req);
- new LoginRedirector(req).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..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,11 +16,14 @@ 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;
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 +37,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 +106,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 +141,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());
@@ -158,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/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) {
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..8792a0225 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
@@ -184,16 +184,24 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
templateDataModel.put("body", bodyString);
// Tell the template and any directives it uses that we're processing a page template.
- templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE);
- writePage(templateDataModel, config, vreq, response);
+ templateDataModel.put("templateType", PAGE_TEMPLATE_TYPE);
+
+ writePage(templateDataModel, config, vreq, response, values.getStatusCode());
}
protected void doRedirect(HttpServletRequest request, HttpServletResponse response, ResponseValues values)
throws ServletException, IOException {
String redirectUrl = values.getRedirectUrl();
+ setResponseStatus(response, values.getStatusCode());
response.sendRedirect(redirectUrl);
}
+ private void setResponseStatus(HttpServletResponse response, int statusCode) {
+ if (statusCode > 0) {
+ response.setStatus(statusCode);
+ }
+ }
+
protected void doForward(HttpServletRequest request, HttpServletResponse response, ResponseValues values)
throws ServletException, IOException {
String forwardUrl = values.getForwardUrl();
@@ -306,11 +314,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;
}
@@ -330,9 +345,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);
@@ -365,11 +377,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
// This value is used only in stylesheets.ftl and already contains the context path.
map.put("stylesheetPath", UrlBuilder.getUrl(themeDir + "/css"));
-// String bannerImage = portal.getBannerImage();
-// if ( ! StringUtils.isEmpty(bannerImage)) {
-// map.put("bannerImage", UrlBuilder.getUrl(themeDir + "site_icons/" + bannerImage));
-// }
-
String flashMessage = DisplayMessage.getMessageAndClear(vreq);
if (! flashMessage.isEmpty()) {
map.put("flash", flashMessage);
@@ -448,18 +455,24 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
}
protected void writePage(Map root, Configuration config,
- HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException {
- writeTemplate(getPageTemplateName(), root, config, request, response);
+ HttpServletRequest request, HttpServletResponse response, int statusCode) throws TemplateProcessingException {
+ writeTemplate(getPageTemplateName(), root, config, request, response, statusCode);
}
protected void writeTemplate(String templateName, Map map, Configuration config,
- HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException {
- StringWriter sw = processTemplate(templateName, map, config, request);
- write(sw, response);
+ HttpServletRequest request, HttpServletResponse response) throws TemplateProcessingException {
+ writeTemplate(templateName, map, config, request, response, 0);
+ }
+
+ protected void writeTemplate(String templateName, Map map, Configuration config,
+ HttpServletRequest request, HttpServletResponse response, int statusCode) throws TemplateProcessingException {
+ StringWriter sw = processTemplate(templateName, map, config, request);
+ write(sw, response, statusCode);
}
- protected void write(StringWriter sw, HttpServletResponse response) {
+ protected void write(StringWriter sw, HttpServletResponse response, int statusCode) {
try {
+ setResponseStatus(response, statusCode);
PrintWriter out = response.getWriter();
out.print(sw);
} catch (IOException e) {
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java
index 303ca289e..23d9082fe 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/IndividualController.java
@@ -100,7 +100,7 @@ public class IndividualController extends FreemarkerHttpServlet {
// Check to see if the request is for a non-information resource, redirect if it is.
String redirectURL = checkForRedirect ( url, vreq );
if( redirectURL != null ){
- return new RedirectResponseValues(redirectURL);
+ return new RedirectResponseValues(redirectURL, HttpServletResponse.SC_SEE_OTHER);
}
Individual individual = null;
@@ -463,12 +463,19 @@ public class IndividualController extends FreemarkerHttpServlet {
return null;
}
-
- private static Pattern URI_PATTERN = Pattern.compile("^/individual/([^/]*)$");
- //Redirect if the request is for http://hostname/individual/localname
- // if accept is nothing or text/html redirect to ???
- // if accept is some RDF thing redirect to the URL for RDF
+ /*
+ * Following recipe 3 from "Best Practice Recipes for Publishing RDF Vocabularies."
+ * See http://www.w3.org/TR/swbp-vocab-pub/#recipe3.
+ * The basic idea is that a URI like http://vivo.cornell.edu/individual/n1234
+ * identifies a real world individual. HTTP cannot send that as the response
+ * to a GET request because it can only send bytes and not things. The server
+ * sends a 303, to mean "you asked for something I cannot send you, but I can
+ * send you this other stream of bytes about that thing."
+ * In the case of a request like http://vivo.cornell.edu/individual/n1234/n1234.rdf,
+ * the request is for a set of bytes rather than an individual, so no 303 is needed.
+ */
+ private static Pattern URI_PATTERN = Pattern.compile("^/individual/([^/]*)$");
private String checkForRedirect(String url, VitroRequest vreq) {
Matcher m = URI_PATTERN.matcher(url);
if( m.matches() && m.groupCount() == 1 ){
@@ -506,7 +513,11 @@ public class IndividualController extends FreemarkerHttpServlet {
protected ContentType checkForLinkedDataRequest(String url, VitroRequest vreq ) {
try {
Matcher m;
- // Check for url param specifying format
+ /*
+ * Check for url param specifying format.
+ * Example: http://vivo.cornell.edu/individual/n23?format=rdfxml
+ * This request will trigger a redirect with a 303.
+ */
String formatParam = (String) vreq.getParameter("format");
if (formatParam != null) {
m = RDFXML_FORMAT.matcher(formatParam);
@@ -523,7 +534,11 @@ public class IndividualController extends FreemarkerHttpServlet {
}
}
- //check the accept header
+ /*
+ * Check the accept header. This request will trigger a
+ * redirect with a 303, because the request is for an individual
+ * but the server can only provide a set of bytes.
+ */
String acceptHeader = vreq.getHeader("accept");
if (acceptHeader != null) {
String ctStr = ContentType.getBestContentType(
@@ -538,10 +553,12 @@ public class IndividualController extends FreemarkerHttpServlet {
}
/*
- * check for parts of URL that indicate request for RDF
- http://vivo.cornell.edu/individual/n23/n23.rdf
- http://vivo.cornell.edu/individual/n23/n23.n3
- http://vivo.cornell.edu/individual/n23/n23.ttl
+ * Check for parts of URL that indicate request for RDF
+ * http://vivo.cornell.edu/individual/n23/n23.rdf
+ * http://vivo.cornell.edu/individual/n23/n23.n3
+ * http://vivo.cornell.edu/individual/n23/n23.ttl
+ * This request will not trigger a redirect and 303, because
+ * the request is for a set of bytes rather than an individual.
*/
m = RDF_REQUEST.matcher(url);
if( m.matches() ) {
@@ -555,8 +572,7 @@ public class IndividualController extends FreemarkerHttpServlet {
if( m.matches() ) {
return ContentType.TURTLE;
}
-
-
+
} catch (Throwable th) {
log.error("problem while checking accept header " , th);
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java
index 229a0c5a8..c4c6b5f4b 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/BaseResponseValues.java
@@ -22,6 +22,11 @@ public abstract class BaseResponseValues implements ResponseValues {
BaseResponseValues(ContentType contentType) {
this.contentType = contentType;
}
+
+ BaseResponseValues(ContentType contentType, int statusCode) {
+ this.contentType = contentType;
+ this.statusCode = statusCode;
+ }
@Override
public int getStatusCode() {
@@ -38,6 +43,7 @@ public abstract class BaseResponseValues implements ResponseValues {
return contentType;
}
+ @Override
public void setContentType(ContentType contentType) {
this.contentType = contentType;
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java
index 470139e0b..4a3107857 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/RdfResponseValues.java
@@ -14,6 +14,11 @@ public class RdfResponseValues extends BaseResponseValues {
this.model = model;
}
+ public RdfResponseValues(ContentType contentType, Model model, int statusCode) {
+ super(contentType, statusCode);
+ this.model = model;
+ }
+
@Override
public Model getModel() {
return model;
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java
index d72d6e22d..6ebdef627 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/ResponseValues.java
@@ -28,6 +28,8 @@ public interface ResponseValues {
public ContentType getContentType();
+ public void setContentType(ContentType contentType);
+
public Model getModel();
}
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java
index 7e35ed737..b02ce7b0c 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/responsevalues/TemplateResponseValues.java
@@ -49,7 +49,9 @@ public class TemplateResponseValues extends BaseResponseValues {
}
public static TemplateResponseValues getTemplateResponseValuesFromException(ExceptionResponseValues responseValues) {
- return new TemplateResponseValues(responseValues.getTemplateName(), responseValues.getMap());
+ return new TemplateResponseValues(responseValues.getTemplateName(),
+ responseValues.getMap(),
+ responseValues.getStatusCode());
}
}
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);
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDao.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDao.java
index 46115df77..927538a31 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDao.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/UserAccountsDao.java
@@ -40,11 +40,6 @@ public interface UserAccountsDao {
*/
UserAccount getUserAccountByExternalAuthId(String externalAuthId);
- /**
- * Is this UserAccount a root user?
- */
- boolean isRootUser(UserAccount userAccount);
-
/**
* Create a new UserAccount in the model.
*
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/UserAccountsDaoFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/UserAccountsDaoFiltering.java
index 12b725c5b..2a08eb9f8 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/UserAccountsDaoFiltering.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/UserAccountsDaoFiltering.java
@@ -47,11 +47,6 @@ public class UserAccountsDaoFiltering extends BaseFiltering implements
return innerDao.getUserAccountByExternalAuthId(externalAuthId);
}
- @Override
- public boolean isRootUser(UserAccount userAccount) {
- return innerDao.isRootUser(userAccount);
- }
-
@Override
public String insertUserAccount(UserAccount userAccount) {
return innerDao.insertUserAccount(userAccount);
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/IndividualJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java
index 26adf499a..1a282b6ef 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.isClassProhibitedFromSearch(typeURI)) {
- return false;
+ return true;
}
}
}
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 d16fdbbad..a91740814 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);
@@ -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;
}
}
@@ -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/src/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java
index 53db0d845..3621cbf34 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java
@@ -103,6 +103,7 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
USERACCOUNT_EXTERNAL_AUTH_ID));
u.setPermissionSetUris(getPropertyResourceURIValues(r,
USERACCOUNT_HAS_PERMISSION_SET));
+ u.setRootUser(isResourceOfType(r, USERACCOUNT_ROOT_USER));
return u;
} finally {
getOntModel().leaveCriticalSection();
@@ -157,21 +158,6 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
return getUserAccountByUri(userUri);
}
- @Override
- public boolean isRootUser(UserAccount userAccount) {
- if (userAccount == null) {
- return false;
- }
-
- getOntModel().enterCriticalSection(Lock.READ);
- try {
- OntResource r = getOntModel().getOntResource(userAccount.getUri());
- return isResourceOfType(r, USERACCOUNT_ROOT_USER);
- } finally {
- getOntModel().leaveCriticalSection();
- }
- }
-
@Override
public String insertUserAccount(UserAccount userAccount) {
if (userAccount == null) {
@@ -214,6 +200,10 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
USERACCOUNT_HAS_PERMISSION_SET,
userAccount.getPermissionSetUris(), model);
+ if (userAccount.isRootUser()) {
+ model.add(res, RDF.type, USERACCOUNT_ROOT_USER);
+ }
+
userAccount.setUri(userUri);
return userUri;
} catch (InsertException e) {
@@ -268,6 +258,13 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
updatePropertyResourceURIValues(res,
USERACCOUNT_HAS_PERMISSION_SET,
userAccount.getPermissionSetUris(), model);
+
+ if (userAccount.isRootUser()) {
+ model.add(res, RDF.type, USERACCOUNT_ROOT_USER);
+ } else {
+ model.remove(res, RDF.type, USERACCOUNT_ROOT_USER);
+ }
+
} finally {
model.leaveCriticalSection();
}
@@ -367,7 +364,7 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
throw new InsertException("Could not create URI for individual: "
+ errMsg);
}
-
+
private boolean isUriUsed(String uri) {
return (getOntModel().getOntResource(uri) != null);
}
@@ -385,7 +382,7 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao
if (type == null) {
return false;
}
-
+
StmtIterator stmts = getOntModel().listStatements(r, RDF.type, type);
if (stmts.hasNext()) {
stmts.close();
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..d980dd8d7 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;
@@ -21,22 +23,30 @@ 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.logging.Log;
import org.apache.commons.logging.LogFactory;
-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.controller.freemarker.FreemarkerHttpServlet;
+import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective;
+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
* 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
@@ -47,15 +57,15 @@ 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 htmlTemplateName;
- private String textTemplateName;
+ private String templateName = "";
+ private String htmlContent = "";
+ private String textContent = "";
private Map bodyMap = Collections.emptyMap();
/**
@@ -67,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();
@@ -115,10 +123,6 @@ 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 + "'");
@@ -130,27 +134,41 @@ public class FreemarkerEmailMessage {
this.subject = nonNull(subject, "");
}
- public void setHtmlTemplate(String templateName) {
- this.htmlTemplateName = nonNull(templateName, "");
+ public void setHtmlContent(String htmlContent) {
+ this.htmlContent = nonNull(htmlContent, "");
}
- public void setTextTemplate(String templateName) {
- this.textTemplateName = nonNull(templateName, "");
+ public void setTextContent(String textContent) {
+ this.textContent = nonNull(textContent, "");
+ }
+
+ 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() {
+ bodyMap.putAll(FreemarkerHttpServlet.getDirectivesForAllEnvironments());
+ bodyMap.put("email", new EmailDirective(this));
+
+ try {
+ Template template = config.getTemplate(templateName);
+ template.process(bodyMap, new StringWriter());
+ } catch (TemplateException e) {
+ log.error(e, e);
+ } catch (IOException e) {
+ log.error(e, e);
}
}
public void send() {
- String textBody = figureMessageBody(textTemplateName);
- String htmlBody = figureMessageBody(htmlTemplateName);
-
try {
MimeMessage msg = new MimeMessage(session);
msg.setReplyTo(new Address[] { replyToAddress });
@@ -167,19 +185,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);
}
}
@@ -193,26 +211,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.
- */
- 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();
@@ -235,7 +233,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
new file mode 100644
index 000000000..58ca99ada
--- /dev/null
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/EmailDirective.java
@@ -0,0 +1,98 @@
+/* $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 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;
+
+/**
+ * Process the inputs for a FreemarkerEmailMessage.
+ *
+ * @see FreemarkerEmailMessage
+ */
+public class EmailDirective extends BaseTemplateDirectiveModel {
+
+ private static final Log log = LogFactory.getLog(EmailDirective.class);
+
+ private final FreemarkerEmailMessage message;
+
+ public EmailDirective(FreemarkerEmailMessage message) {
+ this.message = message;
+ }
+
+ @Override
+ public void execute(Environment env, Map params, TemplateModel[] loopVars,
+ TemplateDirectiveBody body) throws TemplateException, IOException {
+
+ String subject = getOptionalSimpleScalarParameter(params, "subject");
+ if (subject != null) {
+ message.setSubject(subject);
+ }
+
+ String htmlContent = getOptionalSimpleScalarParameter(params, "html");
+ if (htmlContent != null) {
+ message.setHtmlContent(htmlContent);
+ }
+
+ String textContent = getOptionalSimpleScalarParameter(params, "text");
+ if (textContent != null) {
+ message.setTextContent(textContent);
+ }
+
+ 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;
+ }
+}
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/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/User.java
index e533847e5..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,27 @@ 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() {
+ if (currentUser == null) {
+ return "";
+ } else {
+ return currentUser.getFirstName();
+ }
+ }
+
+ public String getLastName() {
+ if (currentUser == null) {
+ return "";
+ } else {
+ return currentUser.getLastName();
+ }
}
public boolean getHasSiteAdminAccess() {
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());
}
}
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;
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java
index bba2ad4ba..4a08a9766 100644
--- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java
@@ -12,7 +12,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -91,6 +90,27 @@ public class UserAccountsSelectorTest extends AbstractTestClass {
Collections
.singleton("http://vivo.mydomain.edu/individual/role2"),
acct.getPermissionSetUris());
+ assertEquals("rootUser", false, acct.isRootUser());
+ }
+
+ @Test
+ public void checkFieldsForRootUser() {
+ selectOnCriteria(1, 8, DEFAULT_ORDERING, "", "");
+ assertSelectedUris(10, "user08");
+
+ UserAccount acct = selection.getUserAccounts().get(0);
+ assertEquals("uri", "http://vivo.mydomain.edu/individual/user08",
+ acct.getUri());
+ assertEquals("email", "email@henry.edu", acct.getEmailAddress());
+ assertEquals("firstName", "Mary", acct.getFirstName());
+ assertEquals("lastName", "McInerney", acct.getLastName());
+ assertEquals("password", "garbage", acct.getMd5Password());
+ assertEquals("expires", 0L, acct.getPasswordLinkExpires());
+ assertEquals("loginCount", 7, acct.getLoginCount());
+ assertEquals("status", UserAccount.Status.ACTIVE, acct.getStatus());
+ assertEqualSets("permissions", Collections. emptySet(),
+ acct.getPermissionSetUris());
+ assertEquals("rootUser", true, acct.isRootUser());
}
// ----------------------------------------------------------------------
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3
index 85d5895c1..7e39d30fb 100644
--- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3
@@ -101,6 +101,7 @@ mydomain:user07
mydomain:user08
a auth:UserAccount ;
+ a auth:RootUserAccount ;
auth:emailAddress "email@henry.edu" ;
auth:firstName "Mary" ;
auth:lastName "McInerney" ;
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/test/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java
index 80042b241..7f64b7b14 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
@@ -18,10 +18,13 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import org.apache.log4j.Level;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import stubs.edu.cornell.mannlib.vitro.webapp.config.ConfigurationPropertiesStub;
+import stubs.edu.cornell.mannlib.vitro.webapp.dao.IndividualDaoStub;
import stubs.edu.cornell.mannlib.vitro.webapp.dao.UserAccountsDaoStub;
import stubs.edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryStub;
import stubs.javax.servlet.ServletConfigStub;
@@ -32,7 +35,10 @@ 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.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.AuthenticatorStub;
import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean;
@@ -46,6 +52,7 @@ public class AuthenticateTest extends AbstractTestClass {
private ServletContextStub servletContext;
private WebappDaoFactoryStub webappDaoFactory;
private UserAccountsDaoStub userAccountsDao;
+ private IndividualDaoStub individualDao;
private ServletConfigStub servletConfig;
private HttpSessionStub session;
private HttpServletRequestStub request;
@@ -122,8 +129,11 @@ public class AuthenticateTest extends AbstractTestClass {
userAccountsDao.addUser(createUserFromUserInfo(OLD_SELF));
userAccountsDao.addUser(createUserFromUserInfo(OLD_STRANGER));
+ individualDao = new IndividualDaoStub();
+
webappDaoFactory = new WebappDaoFactoryStub();
webappDaoFactory.setUserAccountsDao(userAccountsDao);
+ webappDaoFactory.setIndividualDao(individualDao);
servletContext = new ServletContextStub();
servletContext.setAttribute("webappDaoFactory", webappDaoFactory);
@@ -143,6 +153,12 @@ public class AuthenticateTest extends AbstractTestClass {
auth = new Authenticate();
auth.init(servletConfig);
+
+ setLoggerLevel(ConfigurationProperties.class, Level.WARN);
+ new ConfigurationPropertiesStub().setBean(servletContext);
+
+ 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..42aa6a104 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
@@ -48,11 +48,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(
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/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/css/vitro.css b/webapp/web/css/vitro.css
index 184c7f688..7ec39d5dd 100644
--- a/webapp/web/css/vitro.css
+++ b/webapp/web/css/vitro.css
@@ -74,3 +74,42 @@
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 h4 {
+ color: #fff;
+ padding: 0 0 0 0;
+}
+.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/edit/forms/autoCompleteDatapropForm.jsp b/webapp/web/edit/forms/autoCompleteDatapropForm.jsp
index cc8d81917..cb1785fcc 100644
--- a/webapp/web/edit/forms/autoCompleteDatapropForm.jsp
+++ b/webapp/web/edit/forms/autoCompleteDatapropForm.jsp
@@ -119,10 +119,10 @@
Model model = (Model)application.getAttribute("jenaOntModel");
editConfig.prepareForDataPropUpdate(model,dps);
formTitle = "Change text for: "+prop.getPublicName()+"";
- submitLabel = "save change";
+ submitLabel = "Save change";
} else {
formTitle = "Add new entry for: "+prop.getPublicName()+"";
- submitLabel = "save entry";
+ submitLabel = "Save entry";
}
%>
diff --git a/webapp/web/edit/forms/autoCompleteObjPropForm.jsp b/webapp/web/edit/forms/autoCompleteObjPropForm.jsp
index 80480c14f..772391ff2 100644
--- a/webapp/web/edit/forms/autoCompleteObjPropForm.jsp
+++ b/webapp/web/edit/forms/autoCompleteObjPropForm.jsp
@@ -111,10 +111,10 @@
if ( prop.getOfferCreateNewOption() ) {
log.debug("property set to offer \"create new\" option; custom form: ["+prop.getCustomEntryForm()+"]");
formTitle = "Select an existing "+rangeClass.getName()+" for "+subject.getName();
- submitLabel = "select existing";
+ submitLabel = "Select existing";
} else {
formTitle = "Add an entry to: "+prop.getDomainPublic()+"";
- submitLabel = "save entry";
+ submitLabel = "Save entry";
}
}
%>
@@ -174,7 +174,7 @@ $(document).ready(function() {
If you don't find the appropriate entry on the selection list,
-
+