Adding login via email/password parameters

This commit is contained in:
Brian Caruso 2013-07-16 12:28:24 -04:00
parent 7905b80df4
commit fb46e64725
3 changed files with 134 additions and 31 deletions

View file

@ -10,9 +10,17 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.ActiveIdentifierBundleFactories;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.Authenticator;
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.BasicAuthenticator;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ExceptionResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ExceptionResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
@ -27,11 +35,64 @@ import edu.cornell.mannlib.vitro.webapp.search.indexing.IndexBuilder;
public class SearchServiceController extends FreemarkerHttpServlet { public class SearchServiceController extends FreemarkerHttpServlet {
private static final Log log = LogFactory.getLog(SearchServiceController.class); private static final Log log = LogFactory.getLog(SearchServiceController.class);
/**
* Attempt to check if there is a email and password in the request parameters.
* If there is not, fall back on the normal usage pattern of requestedAction().
* If there is, then try to authenticate and authorize the
* userAccount associated with the email.
*/
@Override @Override
protected Actions requiredActions(VitroRequest vreq) { protected Actions requiredActions(VitroRequest vreq) {
try{
// Works by side effect: parse the multi-part request and stash FileItems in request
new MultipartHttpServletRequest( vreq );
//first figure out if the password and email login to an account with a password
String pw = vreq.getParameter("password");
String email = vreq.getParameter("email");
log.debug(String.format("email: '%s' password: '%s' ",email,pw));
if( pw == null || email == null || pw.isEmpty() || email.isEmpty()){
return SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS; return SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS;
} }
Authenticator basicAuth = new BasicAuthenticator(vreq);
UserAccount user = basicAuth.getAccountForInternalAuth( email );
log.debug("userAccount is " + user==null?"null":user.getUri() );
if( ! basicAuth.isCurrentPassword( user, pw ) ){
log.debug(String.format("UNAUTHORIZED, password not accepted for %s, account URI: %s",
user.getEmailAddress(), user.getUri()));
return Actions.UNAUTHORIZED;
}else{
log.debug(String.format("password accepted for %s, account URI: %s",
user.getEmailAddress(), user.getUri() ));
}
//then figure out if that account can manage the search index.
IdentifierBundle ids =
ActiveIdentifierBundleFactories.getUserIdentifierBundle(vreq,user);
PolicyIface policy = ServletPolicyList.getPolicies(vreq);
boolean canManageSearchIndex =
PolicyHelper.isAuthorizedForActions( ids, policy,
SimplePermission.MANAGE_SEARCH_INDEX.ACTIONS );
if( canManageSearchIndex ){
return Actions.AUTHORIZED;
}else{
log.debug(String.format("userAccount is unauthorized to" +
" manage the search index.",user.getUri()));
return Actions.UNAUTHORIZED;
}
}catch(Exception ex){
log.error("Error while attempting to log in " +
"to SearchServiceController: " + ex.getMessage());
return Actions.UNAUTHORIZED;
}
}
/** /**
* Handle the different actions. If not specified, the default action is to * Handle the different actions. If not specified, the default action is to
* show the help page. * show the help page.
@ -39,8 +100,6 @@ public class SearchServiceController extends FreemarkerHttpServlet {
@Override @Override
protected ResponseValues processRequest(VitroRequest req) { protected ResponseValues processRequest(VitroRequest req) {
try { try {
// Works by side effect: parse the multi-part request and stash FileItems in request
new MultipartHttpServletRequest( req );
//figure out what action to perform //figure out what action to perform
String pathInfo = req.getPathInfo(); String pathInfo = req.getPathInfo();
@ -62,6 +121,8 @@ public class SearchServiceController extends FreemarkerHttpServlet {
} }
/**
* Process requests to the web service to update a list of URIs in the search index. */
public ResponseValues doUpdateUrisInSearch(HttpServletRequest req ) public ResponseValues doUpdateUrisInSearch(HttpServletRequest req )
throws IOException, ServletException { throws IOException, ServletException {

View file

@ -41,33 +41,39 @@ public class UpdateUrisInIndex {
protected void doUpdateUris(HttpServletRequest req, IndexBuilder builder) protected void doUpdateUris(HttpServletRequest req, IndexBuilder builder)
throws ServletException, IOException{ throws ServletException, IOException{
if( ! ServletFileUpload.isMultipartContent(req) )
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if( ! isMultipart )
throw new ServletException("Expected Multipart Content"); throw new ServletException("Expected Multipart Content");
String enc = getEncoding(req);
String charEncoding = getEncoding(req);
try{ try{
int count = 0; //loop over the fileds and add any URIs to the IndexBuilder queue
ServletFileUpload upload = new ServletFileUpload(); ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iter = upload.getItemIterator(req); FileItemIterator iter = upload.getItemIterator(req);
while( iter.hasNext()){ while( iter.hasNext()){
FileItemStream item = iter.next(); FileItemStream item = iter.next();
String name = item.getFieldName(); String name = item.getFieldName();
if( "email".equals(name) || "password".equals(name) )
continue; //skip the password and email fields
InputStream stream = item.openStream(); InputStream stream = item.openStream();
try{ try{
count = count + addToSearchQueue(builder, new InputStreamReader(stream, charEncoding)); addToSearchQueue(builder, stream, enc);
}finally{ }finally{
stream.close(); stream.close();
builder.doUpdateIndex();
} }
} }
}catch (FileUploadException fex){ }catch (FileUploadException fex){
throw new ServletException("Could not upload file to SearchServiceController", fex); throw new ServletException("Could not upload file to SearchServiceController", fex);
}finally{
builder.doUpdateIndex();
} }
} }
/**
* Get the encoding of the request, default to UTF-8
* since that is in the vitro install instructions
* to put on the connector.
*/
private String getEncoding(HttpServletRequest req){ private String getEncoding(HttpServletRequest req){
String enc = req.getCharacterEncoding(); String enc = req.getCharacterEncoding();
if( enc == null || enc.isEmpty() ){ if( enc == null || enc.isEmpty() ){
@ -83,22 +89,26 @@ public class UpdateUrisInIndex {
return enc; return enc;
} }
private int addToSearchQueue( IndexBuilder builder, Reader in ) /**
* Adds URIs from Reader to search queue.
*/
private void addToSearchQueue( IndexBuilder builder, InputStream stream , String charEncoding )
throws IOException{ throws IOException{
int addedUriCount = 0;
Iterator<String> uris = new UrisFromInputIterator( in ); Iterator<String> uris =
new UrisFromInputIterator( new InputStreamReader(stream, charEncoding) );
while(uris.hasNext()){ while(uris.hasNext()){
String uri = uris.next(); String uri = uris.next();
log.debug("Request to index uri '" + uri + "'"); log.debug("Request to index uri '" + uri + "'");
builder.addToChanged( uri ); builder.addToChanged( uri );
addedUriCount++;
} }
return addedUriCount;
} }
/**
* Iterator for URIs in a reader to make top level methods simpler.
*/
public static class UrisFromInputIterator implements Iterator<String> { public static class UrisFromInputIterator implements Iterator<String> {
BufferedReader reader; BufferedReader reader;
Iterator<String> uris; Iterator<String> uris;
@ -149,10 +159,15 @@ public class UpdateUrisInIndex {
} }
} }
/**
* Removes null and empty elements from in.
* Returned list will not be null.
*/
private static List<String> removeNullAndEmpty(List<String> in ){ private static List<String> removeNullAndEmpty(List<String> in ){
ArrayList<String> out = new ArrayList<String>(); ArrayList<String> out = new ArrayList<String>();
if( in == null )
return out;
for( String s : in ){ for( String s : in ){
if( s != null && !s.trim().isEmpty() ){ if( s != null && !s.trim().isEmpty() ){
out.add(s); out.add(s);
@ -161,12 +176,17 @@ public class UpdateUrisInIndex {
return out; return out;
} }
/**
* Parses a line to a list of URIs.
* Retruned list will not be null.
* No elements in returned list will be empty or null.
*/
protected static List<String> lineToUris(String line){ protected static List<String> lineToUris(String line){
List<String> parts = removeNullAndEmpty( Arrays.asList(commaAndWhitespace.split( line ) )); List<String> parts = removeNullAndEmpty( Arrays.asList(commaAndWhitespace.split( line ) ));
return parts; return parts;
} }
//split uris on whitespace and commas /** Pattern to split URIs on whitespace and commas. */
private static final Pattern commaAndWhitespace = Pattern.compile("[,\\s]"); private static final Pattern commaAndWhitespace = Pattern.compile("[,\\s]");
} }

View file

@ -1,18 +1,40 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> <#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<h2>Search Web Service</h2> <h1>Search Web Service</h1>
<p>Add information here about how to use the Search Web Service.</p> <#if msg?has_content >
<h2>Message:</h2>
<p>${msg}</p>
</#if>
<p>*** FOLLOWING FORM IS TOTALLY MESSED UP WITH A HARDCODED URL ***</p> <h2>Update Search Index for URIs</h2>
<form <p>This service will update the search index for the list of URIs it
action="http://localhost:8080/vivo/searchService/updateUrisInSearch" receives. It expectes a POST with an encoding of
multpart/form-data. The service inspect all parts of this POST for
lists of URIs to reindex. The URIs should be comma or space
seperated. If no information can be found for a URI it will be
ignored.</p>
<p>The request parameters email and password allow the form to be submitted
for a user account. Only internal accounts are supported, external authentication
is not supported.</p>
<h2>Example form for Update Search Index for URIs</h2>
<p>The following form will post to the Update URIs in search service.</p>
<form action="${urls.base}/searchService/updateUrisInSearch"
enctype="multipart/form-data" enctype="multipart/form-data"
method="post"> method="post">
<input type="textarea" name="urisToUpdate"/> <label for="email">Account email</label>
<input type="text" name="email" id="email"/>
<label for="password">Account password</label>
<input type="text" name="password" id="password"/>
<label for="urisToUpdate">List of URIs to update in the search index</label>
<textarea name="urisToUpdate" id="urisToUpdate" rows="4" cols="50" ></textarea>
<button type="submit">submit</button> <button type="submit">submit</button>
</form> </form>