From 663152d8b0ace8c8d6f3fe63e8b00ca5bce1c4e0 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 1 Apr 2015 18:42:31 -0700 Subject: [PATCH 01/67] Using rest-util artifact to extend RestResource to handle Hash-based Message Authentication Code (HMAC) validation in HTTP Authorization headers --- pom.xml | 5 + .../jbei/ice/services/rest/RestResource.java | 132 +++++++++++++++--- 2 files changed, 121 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index 8785f9bf8..407f145fe 100755 --- a/pom.xml +++ b/pom.xml @@ -137,6 +137,11 @@ libSBOLj 0.7.0-SNAPSHOT + + org.jbei.informatics + rest-util + 1.0.0-SNAPSHOT + target diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index 7b0d7ef6e..dce67ecff 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -1,11 +1,26 @@ package org.jbei.ice.services.rest; -import org.jbei.ice.lib.account.SessionHandler; -import org.jbei.ice.lib.common.logging.Logger; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.nio.file.Paths; +import java.security.Key; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.HeaderParam; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; +import org.jbei.auth.Authorization; +import org.jbei.auth.KeyTable; +import org.jbei.auth.hmac.HmacAuthorizor; +import org.jbei.auth.hmac.HmacSignatureFactory; +import org.jbei.ice.lib.account.SessionHandler; +import org.jbei.ice.lib.common.logging.Logger; +import org.jbei.ice.lib.dto.ConfigurationKey; +import org.jbei.ice.lib.utils.Utils; + /** * Parent class for all rest resource objects * @@ -13,46 +28,131 @@ */ public class RestResource { - protected String getUserIdFromSessionHeader(String sessionHeader) { - String userId = SessionHandler.getUserIdBySession(sessionHeader); - if (userId == null) + // do lookup by using existing configuration DATA_DIRECTORY to find key names => key data + private static final KeyTable TABLE = new KeyTable() { + + // keys stored in /var/lib/tomcat6/data/rest-auth by default + private final File directory = Paths.get( + Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), "rest-auth").toFile(); + + @Override + public Key getKey(final String keyId) { + try { + // find file named by keyId in the directory + final File keyFile = new File(directory, keyId); + // collect all lines in the file to a buffer + final StringBuilder encoded = new StringBuilder(); + try (final FileReader reader = new FileReader(keyFile); + final BufferedReader buffered = new BufferedReader(reader);) { + String line; + while ((line = buffered.readLine()) != null) { + encoded.append(line); + } + // after reading all lines, decode value into a Key object + return HmacSignatureFactory.decodeKey(encoded.toString()); + } + } catch (final Throwable t) { + Logger.error("Failed to load rest-auth key " + keyId); + } + return null; + } + + }; + + private static final HmacAuthorizor AUTHORIZOR = new HmacAuthorizor(TABLE); + + @HeaderParam(value = "X-ICE-Authentication-SessionId") + private String sessionId; + + @HeaderParam(value = "Authorization") + private String hmacHeader; + + @Context + private HttpServletRequest request; + + private String userId = null; + + /** + * Extract the User ID from header values in the resource request. + * + * @return a string User ID + * @throws WebApplicationException + * for unauthorized access + */ + protected String getUserId() { + final Authorization auth; + if (userId != null) { + // we've already looked up the userId + return userId; + } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { + userId = auth.getUserId(); + // TODO validation of meaningful userId + // e.g. "admin" account on EDD won't mean anything to ICE + } else if (sessionId != null) { + userId = SessionHandler.getUserIdBySession(sessionId); + } + if (userId == null) { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + return userId; + } + + /** + * @param sessionHeader + * not used + * @return the UserId of the user matching the session value + * @throws WebApplicationException + * if there is no valid UserId + * @deprecated use {@link #getUserId()} instead + */ + @Deprecated + protected String getUserIdFromSessionHeader(final String sessionHeader) { + final String userId = SessionHandler.getUserIdBySession(sessionId); + if (userId == null) { throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } return userId; } - protected Response respond(Response.Status status, Object obj) { - if (obj == null) + protected Response respond(final Response.Status status, final Object obj) { + if (obj == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(status).entity(obj).build(); } - protected Response respond(Object object) { - if (object == null) + protected Response respond(final Object object) { + if (object == null) { return Response.status(Response.Status.NOT_FOUND).build(); + } return Response.status(Response.Status.OK).entity(object).build(); } - protected Response respond(Response.Status status) { + protected Response respond(final Response.Status status) { return Response.status(status).build(); } - protected Response respond(boolean success) { - if (success) + protected Response respond(final boolean success) { + if (success) { return Response.status(Response.Status.OK).build(); + } return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } /** * Used to log user actions * - * @param userId unique user identifier - * @param message log message + * @param userId + * unique user identifier + * @param message + * log message */ - protected void log(String userId, String message) { - if (userId == null) + protected void log(String userId, final String message) { + if (userId == null) { userId = "Unknown"; + } Logger.info(userId + ": " + message); } } From 7c40009483dc7c88c4c5d0a137705a86e2ae426c Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 1 Apr 2015 19:03:41 -0700 Subject: [PATCH 02/67] Adding javadoc to RestResource, convert SearchResource to rely on RestResource to find user --- .../jbei/ice/services/rest/RestResource.java | 39 ++++++-- .../ice/services/rest/SearchResource.java | 88 +++++++++++-------- 2 files changed, 84 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index dce67ecff..ea43cc3ed 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -114,6 +114,16 @@ protected String getUserIdFromSessionHeader(final String sessionHeader) { return userId; } + /** + * Create a {@link Response} object from an entity object. + * + * @param status + * HTTP status code + * @param obj + * entity in response + * @return a Response object for the resource request, uses 500 error response if entity is + * {@code null} + */ protected Response respond(final Response.Status status, final Object obj) { if (obj == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); @@ -122,6 +132,13 @@ protected Response respond(final Response.Status status, final Object obj) { return Response.status(status).entity(obj).build(); } + /** + * Create a {@link Response} object from an entity object. + * + * @param object + * entity in response + * @return a 404 NOT FOUND if object is {@code null}, else a 200 OK response with the entity + */ protected Response respond(final Object object) { if (object == null) { return Response.status(Response.Status.NOT_FOUND).build(); @@ -130,10 +147,24 @@ protected Response respond(final Object object) { return Response.status(Response.Status.OK).entity(object).build(); } + /** + * Create an empty {@link Response} object. + * + * @param status + * HTTP status code to use on the Response + * @return a Response object for the resource request + */ protected Response respond(final Response.Status status) { return Response.status(status).build(); } + /** + * Create an empty {@link Response} object. + * + * @param success + * success/failure flag + * @return a 200 OK response if success is {@code true}, otherwise a 500 error response + */ protected Response respond(final boolean success) { if (success) { return Response.status(Response.Status.OK).build(); @@ -149,10 +180,8 @@ protected Response respond(final boolean success) { * @param message * log message */ - protected void log(String userId, final String message) { - if (userId == null) { - userId = "Unknown"; - } - Logger.info(userId + ": " + message); + protected void log(final String userId, final String message) { + final String who = (userId == null) ? "Unknown" : userId; + Logger.info(who + ": " + message); } } diff --git a/src/main/java/org/jbei/ice/services/rest/SearchResource.java b/src/main/java/org/jbei/ice/services/rest/SearchResource.java index a7d17890f..1b0573600 100644 --- a/src/main/java/org/jbei/ice/services/rest/SearchResource.java +++ b/src/main/java/org/jbei/ice/services/rest/SearchResource.java @@ -1,7 +1,20 @@ package org.jbei.ice.services.rest; +import java.util.Arrays; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + import org.apache.commons.lang.StringUtils; -import org.jbei.ice.lib.account.SessionHandler; + import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.entry.EntryType; import org.jbei.ice.lib.dto.search.SearchQuery; @@ -9,15 +22,9 @@ import org.jbei.ice.lib.search.SearchController; import org.jbei.ice.lib.shared.ColumnField; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.Arrays; -import java.util.List; - /** - * REST resource for searching. Supports keyword search with query params for filtering and - * advanced search + * REST resource for searching. Supports keyword search with query params for filtering and advanced + * search * * @author Hector Plahar */ @@ -27,24 +34,26 @@ public class SearchResource extends RestResource { private SearchController controller = new SearchController(); /** - * Advanced Search. The use of post is mostly for the sequence string for - * blast which can get very long and results in a 413 status code if - * sent via GET + * Advanced Search. The use of post is mostly for the sequence string for blast which can get + * very long and results in a 413 status code if sent via GET + * + * @param searchWeb + * whether to perform a web of registry search or not + * @param query + * parameters to the search * * @return results of the search */ @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) - public Response search( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionHeader, - @DefaultValue("false") @QueryParam("webSearch") boolean searchWeb, - SearchQuery query) { - String userId = SessionHandler.getUserIdBySession(sessionHeader); + public Response search(@DefaultValue("false") @QueryParam("webSearch") final boolean searchWeb, + final SearchQuery query) { + final String userId = getUserId(); try { - SearchResults results = controller.runSearch(userId, query, searchWeb); + final SearchResults results = controller.runSearch(userId, query, searchWeb); return super.respond(Response.Status.OK, results); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return super.respond(Response.Status.INTERNAL_SERVER_ERROR); } @@ -53,41 +62,44 @@ public Response search( /** * Keyword search * - * @param queryString keywords to search on - * @param searchWeb whether to perform a web of registry search or not - * @param offset result start - * @param limit result count upper limit - * @param sort result sort - * @param asc true if return results in ascending order, false otherwise - * @param sessionId user unique session identifier + * @param queryString + * keywords to search on + * @param searchWeb + * whether to perform a web of registry search or not + * @param offset + * result start + * @param limit + * result count upper limit + * @param sort + * result sort + * @param asc + * true if return results in ascending order, false otherwise * @return wrapper around list of search results conforming to query params */ @GET @Produces(MediaType.APPLICATION_JSON) - public Response search( - @QueryParam("q") String queryString, - @DefaultValue("false") @QueryParam("webSearch") boolean searchWeb, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("relevance") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = SessionHandler.getUserIdBySession(sessionId); + public Response search(@QueryParam("q") final String queryString, + @DefaultValue("false") @QueryParam("webSearch") final boolean searchWeb, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("relevance") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { + final String userId = getUserId(); if (StringUtils.isEmpty(userId) && !searchWeb) { return super.respond(Response.Status.FORBIDDEN); } log(userId, "query \'" + queryString + '\''); - SearchQuery query = new SearchQuery(); + final SearchQuery query = new SearchQuery(); query.setQueryString(queryString); - SearchQuery.Parameters parameters = query.getParameters(); + final SearchQuery.Parameters parameters = query.getParameters(); parameters.setRetrieveCount(limit); parameters.setStart(offset); parameters.setSortAscending(asc); parameters.setSortField(ColumnField.valueOf(sort.toUpperCase())); - List types = Arrays.asList(EntryType.values()); + final List types = Arrays.asList(EntryType.values()); query.setEntryTypes(types); return super.respond(controller.runSearch(userId, query, searchWeb)); } From 483328ea51e279798b610dad0ed6bb378d5c616f Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 2 Apr 2015 16:09:56 -0700 Subject: [PATCH 03/67] Converting more REST resources to use parent class to find current user, adding Javadoc and fixing warnings --- .../services/rest/AccessTokenResource.java | 32 +- .../services/rest/ArrayDataJSONHandler.java | 39 ++- .../ice/services/rest/BulkUploadResource.java | 330 +++++++++++------- .../ice/services/rest/ConfigResource.java | 66 ++-- .../jbei/ice/services/rest/FileResource.java | 310 +++++++++------- 5 files changed, 472 insertions(+), 305 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java b/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java index 03442e830..bb723b057 100644 --- a/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java +++ b/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java @@ -26,18 +26,18 @@ public class AccessTokenResource extends RestResource { private final AccountController accountController = new AccountController(); /** - * Creates a new access token for the user referenced in the parameter, after - * the credentials (username and password) are validated. If one already exists, it is - * invalidated + * Creates a new access token for the user referenced in the parameter, after the credentials + * (username and password) are validated. If one already exists, it is invalidated * - * @param transfer wraps username and password + * @param transfer + * wraps username and password * @return account information including a valid session id if credentials validate */ @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) - public Response create(AccountTransfer transfer) { - AccountTransfer info = accountController.authenticate(transfer); + public Response create(final AccountTransfer transfer) { + final AccountTransfer info = accountController.authenticate(transfer); if (info == null) { Logger.warn("Authentication failed for user " + transfer.getEmail()); return respond(Response.Status.UNAUTHORIZED); @@ -50,29 +50,33 @@ public Response create(AccountTransfer transfer) { /** * Invalidates the specified session information. * - * @param sessionId session identifier to invalidates + * @param sessionId + * session identifier to invalidates */ @DELETE - public void deleteToken(@HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { - getUserIdFromSessionHeader(sessionId); + public void deleteToken(@HeaderParam("X-ICE-Authentication-SessionId") final String sessionId) { + // ensure the user is valid + getUserId(); accountController.invalidate(sessionId); } /** * Retrieve account information for user referenced by session id * - * @param sessionId unique session identifier for logged in user + * @param sessionId + * unique session identifier for logged in user * @return account information for session if session is valid, null otherwise */ @GET @Produces(MediaType.APPLICATION_JSON) - public AccountTransfer get(@HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public AccountTransfer get(@HeaderParam("X-ICE-Authentication-SessionId") final String sessionId) { if (AccountController.isAuthenticated(sessionId)) { - Account account = accountController.getAccountBySessionKey(sessionId); - if (account == null) + final Account account = accountController.getAccountBySessionKey(sessionId); + if (account == null) { return null; + } - AccountTransfer transfer = account.toDataTransferObject(); + final AccountTransfer transfer = account.toDataTransferObject(); transfer.setSessionId(sessionId); transfer.setAdmin(accountController.isAdministrator(account)); return transfer; diff --git a/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java b/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java index 0d8b33feb..e43d9ac84 100644 --- a/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java +++ b/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java @@ -10,6 +10,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; + import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; @@ -19,12 +20,10 @@ import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; -import org.jbei.ice.lib.dao.IDataTransferModel; - import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.reflect.TypeToken; + +import org.jbei.ice.lib.dao.IDataTransferModel; /** * @author Hector Plahar @@ -33,39 +32,43 @@ @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class ArrayDataJSONHandler implements MessageBodyWriter>, - MessageBodyReader> { + MessageBodyReader> { @Override - public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + public boolean isReadable(final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType) { return true; } @Override - public ArrayList readFrom(Class> type, Type genericType, - Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - InputStream entityStream) - throws IOException, WebApplicationException { - Gson gson = new GsonBuilder().create(); + public ArrayList readFrom(final Class> type, + final Type genericType, final Annotation[] annotations, final MediaType mediaType, + final MultivaluedMap httpHeaders, final InputStream entityStream) + throws IOException, WebApplicationException { + final Gson gson = new GsonBuilder().create(); try (Reader in = new InputStreamReader(entityStream)) { return gson.fromJson(in, type); } } @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + public boolean isWriteable(final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType) { return true; } @Override - public long getSize(ArrayList iDataTransferModels, Class type, Type genericType, Annotation[] - annotations, MediaType mediaType) { + public long getSize(final ArrayList iDataTransferModels, + final Class type, final Type genericType, final Annotation[] annotations, + final MediaType mediaType) { return 0; } @Override - public void writeTo(ArrayList data, Class type, Type genericType, Annotation[] annotations, - MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) - throws IOException, WebApplicationException { - Gson gson = new GsonBuilder().setPrettyPrinting().create(); + public void writeTo(final ArrayList data, final Class type, + final Type genericType, final Annotation[] annotations, final MediaType mediaType, + final MultivaluedMap httpHeaders, final OutputStream entityStream) + throws IOException, WebApplicationException { + final Gson gson = new GsonBuilder().setPrettyPrinting().create(); try (Writer out = new OutputStreamWriter(entityStream)) { gson.toJson(data, out); } diff --git a/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java b/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java index 2cff948a2..353bbdadd 100644 --- a/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java +++ b/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java @@ -1,9 +1,32 @@ package org.jbei.ice.services.rest; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; + import org.jbei.ice.lib.access.AuthorizationException; import org.jbei.ice.lib.bulkupload.BulkEntryCreator; import org.jbei.ice.lib.bulkupload.BulkUploadController; @@ -19,18 +42,6 @@ import org.jbei.ice.lib.entry.sequence.SequenceController; import org.jbei.ice.lib.utils.Utils; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.io.File; -import java.io.InputStream; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - /** * Rest API for interacting with Bulk upload resources * @@ -42,19 +53,26 @@ public class BulkUploadResource extends RestResource { private BulkUploadController controller = new BulkUploadController(); private BulkEntryCreator creator = new BulkEntryCreator(); + /** + * @param info + * @param id + * @param offset + * @param limit + * @return model object for bulk upload + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public BulkUploadInfo read(@Context UriInfo info, @PathParam("id") long id, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("50") @QueryParam("limit") int limit, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public BulkUploadInfo read(@Context final UriInfo info, @PathParam("id") final long id, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("50") @QueryParam("limit") final int limit) { + final String userId = getUserId(); try { - Logger.info(userId + ": retrieving bulk import with id \"" + id + "\" [" + offset + ", " + limit + "]"); + Logger.info(userId + ": retrieving bulk import with id \"" + id + "\" [" + offset + + ", " + limit + "]"); return controller.getBulkImport(userId, id, offset, limit); - } catch (Exception e) { + } catch (final Exception e) { return null; } } @@ -62,87 +80,107 @@ public BulkUploadInfo read(@Context UriInfo info, @PathParam("id") long id, /** * Retrieves permissions associated with an upload * - * @param sessionId unique session identifier for the user making request - * @param id unique identifier for the upload + * @param id + * unique identifier for the upload * @return retrieved permissions for specified upload if user has required permissions */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public Response getUploadPermissions(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - List permissionList = controller.getUploadPermissions(userId, id); + public Response getUploadPermissions(@PathParam("id") final long id) { + final String userId = getUserId(); + final List permissionList = controller.getUploadPermissions(userId, id); return super.respond(permissionList); } /** * Add upload permission * - * @param sessionId unique session identifier for the user making request - * @param id unique identifier for the upload + * @param id + * unique identifier for the upload + * @param accessPermission + * model object for permissions applied to upload + * @return Response with the added permission */ @POST @Path("/{id}/permissions") - public Response addPermission(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - AccessPermission accessPermission) { - String userId = getUserIdFromSessionHeader(sessionId); - AccessPermission permission = controller.addPermission(userId, id, accessPermission); + public Response addPermission(@PathParam("id") final long id, + final AccessPermission accessPermission) { + final String userId = getUserId(); + final AccessPermission permission = controller.addPermission(userId, id, accessPermission); return super.respond(permission); } + /** + * @param id + * @param permissionId + * @return Response with success or failure of permissions delete + */ @DELETE @Path("/{id}/permissions/{pid}") - public Response removePermission(@PathParam("id") long id, - @PathParam("pid") long permissionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - boolean success = controller.deletePermission(userId, id, permissionId); + public Response removePermission(@PathParam("id") final long id, + @PathParam("pid") final long permissionId) { + final String userId = getUserId(); + final boolean success = controller.deletePermission(userId, id, permissionId); return super.respond(success); } + /** + * @param uploadId + * @param fileInputStream + * @param entryId + * @param contentDispositionHeader + * @return Response with sequence information if upload is successful + */ @POST @Path("/{id}/sequence") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response uploadSequenceFile(@PathParam("id") long uploadId, - @FormDataParam("file") InputStream fileInputStream, - @FormDataParam("entryId") long entryId, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response uploadSequenceFile(@PathParam("id") final long uploadId, + @FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("entryId") final long entryId, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - String fileName = contentDispositionHeader.getFileName(); - String userId = super.getUserIdFromSessionHeader(sessionId); - String sequence = IOUtils.toString(fileInputStream); - SequenceInfo sequenceInfo = controller.addSequence(userId, uploadId, entryId, sequence, fileName); - if (sequenceInfo == null) + final String fileName = contentDispositionHeader.getFileName(); + final String userId = getUserId(); + final String sequence = IOUtils.toString(fileInputStream); + final SequenceInfo sequenceInfo = controller.addSequence(userId, uploadId, entryId, + sequence, fileName); + if (sequenceInfo == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(Response.Status.OK).entity(sequenceInfo).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } + /** + * @param uploadId + * @param fileInputStream + * @param entryId + * @param contentDispositionHeader + * @return Response with information on attachment upload + */ @POST @Path("/{id}/attachment") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response uploadAttachmentFile(@PathParam("id") long uploadId, - @FormDataParam("file") InputStream fileInputStream, - @FormDataParam("entryId") long entryId, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response uploadAttachmentFile(@PathParam("id") final long uploadId, + @FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("entryId") final long entryId, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - String fileName = contentDispositionHeader.getFileName(); - String userId = super.getUserIdFromSessionHeader(sessionId); - AttachmentInfo attachmentInfo = controller.addAttachment(userId, uploadId, entryId, fileInputStream, - fileName); - if (attachmentInfo == null) + final String fileName = contentDispositionHeader.getFileName(); + final String userId = getUserId(); + final AttachmentInfo attachmentInfo = controller.addAttachment(userId, uploadId, + entryId, fileInputStream, fileName); + if (attachmentInfo == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(Response.Status.OK).entity(attachmentInfo).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } @@ -151,162 +189,208 @@ public Response uploadAttachmentFile(@PathParam("id") long uploadId, /** * Creates or updates a list of entries that are to be associated with the specified bulk upload * + * @param id + * @param info + * * @return wrapper around list of created or updated entries */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public BulkUploadInfo updateList(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @PathParam("id") long id, BulkUploadInfo info) { - String userId = getUserIdFromSessionHeader(sessionId); + public BulkUploadInfo updateList(@PathParam("id") final long id, final BulkUploadInfo info) { + final String userId = getUserId(); return creator.createOrUpdateEntries(userId, id, info.getEntryList()); } + /** + * @return Response with pending upload information + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/pending") - public Response getPendingUploads(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response getPendingUploads() { try { - String userId = getUserIdFromSessionHeader(sessionId); - HashMap> pending = controller.getPendingImports(userId); + final String userId = getUserId(); + final HashMap> pending = controller + .getPendingImports(userId); return Response.status(Response.Status.OK).entity(pending).build(); - } catch (AuthorizationException ae) { + } catch (final AuthorizationException ae) { return respond(Response.Status.INTERNAL_SERVER_ERROR); } } + /** + * @param id + * @param info + * @return Response with upload information on renamed upload + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/name") - public Response updateName(@PathParam("id") long id, BulkUploadInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - Logger.info(userId + ": updating bulk upload name for " + info.getId() + " with value " + info.getName()); - BulkUploadInfo result = creator.renameBulkUpload(userId, id, info.getName()); - if (result == null) + public Response updateName(@PathParam("id") final long id, final BulkUploadInfo info) { + final String userId = getUserId(); + Logger.info(userId + ": updating bulk upload name for " + info.getId() + " with value " + + info.getName()); + final BulkUploadInfo result = creator.renameBulkUpload(userId, id, info.getName()); + if (result == null) { return respond(Response.Status.INTERNAL_SERVER_ERROR); + } return respond(Response.Status.OK, result); } + /** + * @param id + * @param info + * @return Response with updated bulk upload info + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/status") - public Response updateStatus( - @PathParam("id") long id, - BulkUploadInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - Logger.info(userId + ": updating bulk upload status for " + info.getId() + " to " + info.getStatus()); - BulkUploadInfo resp = creator.updateStatus(userId, id, info.getStatus()); - if (resp == null) + public Response updateStatus(@PathParam("id") final long id, final BulkUploadInfo info) { + final String userId = getUserId(); + Logger.info(userId + ": updating bulk upload status for " + info.getId() + " to " + + info.getStatus()); + final BulkUploadInfo resp = creator.updateStatus(userId, id, info.getStatus()); + if (resp == null) { return super.respond(Response.Status.BAD_REQUEST); + } return super.respond(resp); } + /** + * @param uploadId + * @param data + * @return Response with created part data + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry") - public Response createEntry(@PathParam("id") long uploadId, - PartData data, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response createEntry(@PathParam("id") final long uploadId, final PartData data) { try { - String userId = getUserIdFromSessionHeader(sessionId); + final String userId = getUserId(); Logger.info(userId + ": adding entry to upload \"" + uploadId + "\""); - PartData result = creator.createEntry(userId, uploadId, data); + final PartData result = creator.createEntry(userId, uploadId, data); return respond(result); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } + /** + * @param uploadId + * @param entryId + * @param data + * @return Response with updated part data + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry/{entryId}") - public Response updateEntry(@PathParam("id") long uploadId, - @PathParam("entryId") long entryId, - PartData data, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response updateEntry(@PathParam("id") final long uploadId, + @PathParam("entryId") final long entryId, final PartData data) { try { - String userId = getUserIdFromSessionHeader(sessionId); - Logger.info(userId + ": updating entry \"" + entryId + "\" for upload \"" + uploadId + "\""); - PartData result = creator.updateEntry(userId, uploadId, entryId, data); + final String userId = getUserId(); + Logger.info(userId + ": updating entry \"" + entryId + "\" for upload \"" + uploadId + + "\""); + final PartData result = creator.updateEntry(userId, uploadId, entryId, data); return respond(result); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } + /** + * @param info + * @return a bulk upload info object + */ @PUT @Produces(MediaType.APPLICATION_JSON) - public BulkUploadInfo create(BulkUploadInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public BulkUploadInfo create(final BulkUploadInfo info) { + final String userId = getUserId(); Logger.info(userId + ": creating bulk upload draft"); return controller.create(userId, info); } + /** + * @return all bulk uploads for the current user + */ @GET @Produces(MediaType.APPLICATION_JSON) - public ArrayList query(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public ArrayList query() { + final String userId = getUserId(); Logger.info(userId + ": retrieving bulk upload drafts"); return controller.retrieveByUser(userId, userId); } + /** + * @param fileInputStream + * @param type + * @param contentDispositionHeader + * @return Response with the id of the imported bulk upload + */ @POST @Path("file") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response post(@FormDataParam("file") InputStream fileInputStream, - @FormDataParam("type") String type, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response post(@FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("type") final String type, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - String userId = getUserIdFromSessionHeader(sessionId); - String fileName = userId + "-" + contentDispositionHeader.getFileName(); - File file = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + final String userId = getUserId(); + final String fileName = userId + "-" + contentDispositionHeader.getFileName(); + final File file = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), "bulk-import", fileName).toFile(); FileUtils.copyInputStreamToFile(fileInputStream, file); - EntryType addType = EntryType.valueOf(type.toUpperCase()); - FileBulkUpload bulkUpload = new FileBulkUpload(userId, file.toPath(), addType); + final EntryType addType = EntryType.valueOf(type.toUpperCase()); + final FileBulkUpload bulkUpload = new FileBulkUpload(userId, file.toPath(), addType); // converted to string because there is no messagebodywriter for json for long - String importId = Long.toString(bulkUpload.process()); + final String importId = Long.toString(bulkUpload.process()); return Response.status(Response.Status.OK).entity(importId).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()) + .build(); } } + /** + * @param uploadId + * @param entryId + * @return OK response if sequence is deleted + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry/{entryId}/sequence") - public Response deleteEntrySequence(@PathParam("id") long uploadId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response deleteEntrySequence(@PathParam("id") final long uploadId, + @PathParam("entryId") final long entryId) { try { - String userId = getUserIdFromSessionHeader(sessionId); - if (new SequenceController().deleteSequence(userId, entryId)) + final String userId = getUserId(); + if (new SequenceController().deleteSequence(userId, entryId)) { return Response.ok().build(); + } return Response.serverError().build(); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } + /** + * @param uploadId + * @param entryId + * @return OK response if attachment is deleted + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry/{entryId}/attachment") - public Response deleteEntryAttachment(@PathParam("id") long uploadId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response deleteEntryAttachment(@PathParam("id") final long uploadId, + @PathParam("entryId") final long entryId) { try { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.deleteAttachment(userId, uploadId, entryId)) + final String userId = getUserId(); + if (controller.deleteAttachment(userId, uploadId, entryId)) { return Response.ok().build(); + } return Response.serverError().build(); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } diff --git a/src/main/java/org/jbei/ice/services/rest/ConfigResource.java b/src/main/java/org/jbei/ice/services/rest/ConfigResource.java index cd02200a6..ff0595fda 100644 --- a/src/main/java/org/jbei/ice/services/rest/ConfigResource.java +++ b/src/main/java/org/jbei/ice/services/rest/ConfigResource.java @@ -1,16 +1,21 @@ package org.jbei.ice.services.rest; -import org.jbei.ice.lib.config.ConfigurationController; -import org.jbei.ice.lib.dto.Setting; -import org.jbei.ice.lib.dto.search.IndexType; -import org.jbei.ice.lib.search.SearchController; +import java.util.ArrayList; -import javax.ws.rs.*; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; + +import org.jbei.ice.lib.config.ConfigurationController; +import org.jbei.ice.lib.dto.Setting; +import org.jbei.ice.lib.dto.search.IndexType; +import org.jbei.ice.lib.search.SearchController; /** * @author Hector Plahar @@ -24,57 +29,74 @@ public class ConfigResource extends RestResource { /** * Retrieves list of system settings available * - * @param sessionId Session Id for user - * @return list of retrieved system settings that can be changed (including those with no values) + * @return list of retrieved system settings that can be changed (including those with no + * values) */ @GET @Produces(MediaType.APPLICATION_JSON) - public ArrayList get(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public ArrayList get() { + final String userId = getUserId(); return controller.retrieveSystemSettings(userId); } + /** + * @param uriInfo + * @return the version setting of this ICE instance + */ @GET @Path("/version") @Produces(MediaType.APPLICATION_JSON) - public Setting getVersion(@Context UriInfo uriInfo) { - String url = uriInfo.getBaseUri().getAuthority(); + public Setting getVersion(@Context final UriInfo uriInfo) { + final String url = uriInfo.getBaseUri().getAuthority(); return controller.getSystemVersion(url); } /** * Retrieves the value for the specified config key * + * @param key + * config key + * * @return setting containing the passed key and associated value if found */ @GET @Path("/{key}") @Produces(MediaType.APPLICATION_JSON) - public Setting getConfig(@PathParam("key") String key) { + public Setting getConfig(@PathParam("key") final String key) { return controller.getPropertyValue(key); } + /** + * @return Response specifying success or failure of re-index + */ @PUT @Path("/lucene") - public Response buildLuceneIndex(@HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - boolean success = searchController.rebuildIndexes(userId, IndexType.LUCENE); + public Response buildLuceneIndex() { + final String userId = getUserId(); + final boolean success = searchController.rebuildIndexes(userId, IndexType.LUCENE); return super.respond(success); } + /** + * @return Response specifying success or failure of re-index + */ @PUT @Path("/blast") - public Response buildBlastIndex(@HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - boolean success = searchController.rebuildIndexes(userId, IndexType.BLAST); + public Response buildBlastIndex() { + final String userId = getUserId(); + final boolean success = searchController.rebuildIndexes(userId, IndexType.BLAST); return super.respond(success); } + /** + * @param setting + * a config value to update + * @return the updated config key:value + */ @PUT @Produces(MediaType.APPLICATION_JSON) - public Setting update(@HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - Setting setting) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Setting update(final Setting setting) { + final String userId = getUserId(); return controller.updateSetting(userId, setting); } } diff --git a/src/main/java/org/jbei/ice/services/rest/FileResource.java b/src/main/java/org/jbei/ice/services/rest/FileResource.java index 99e513c09..3d36a0e2f 100644 --- a/src/main/java/org/jbei/ice/services/rest/FileResource.java +++ b/src/main/java/org/jbei/ice/services/rest/FileResource.java @@ -1,11 +1,31 @@ package org.jbei.ice.services.rest; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.file.Paths; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; -import org.jbei.ice.lib.account.SessionHandler; + import org.jbei.ice.lib.bulkupload.FileBulkUpload; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dao.DAOFactory; @@ -27,14 +47,6 @@ import org.jbei.ice.lib.utils.EntriesAsCSV; import org.jbei.ice.lib.utils.Utils; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; -import java.io.*; -import java.net.URI; -import java.nio.file.Paths; - /** * @author Hector Plahar */ @@ -44,25 +56,29 @@ public class FileResource extends RestResource { private SequenceController sequenceController = new SequenceController(); private AttachmentController attachmentController = new AttachmentController(); + /** + * @param fileInputStream + * @param contentDispositionHeader + * @return Response with attachment info on uploaded file + */ @POST @Path("attachment") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response post(@FormDataParam("file") InputStream fileInputStream, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response post(@FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - getUserIdFromSessionHeader(sessionId); - String fileName = contentDispositionHeader.getFileName(); - String fileId = Utils.generateUUID(); - File attachmentFile = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + final String fileName = contentDispositionHeader.getFileName(); + final String fileId = Utils.generateUUID(); + final File attachmentFile = Paths.get( + Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), AttachmentController.attachmentDirName, fileId).toFile(); FileUtils.copyInputStreamToFile(fileInputStream, attachmentFile); - AttachmentInfo info = new AttachmentInfo(); + final AttachmentInfo info = new AttachmentInfo(); info.setFileId(fileId); info.setFilename(fileName); return Response.status(Response.Status.OK).entity(info).build(); - } catch (IOException e) { + } catch (final IOException e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } @@ -70,15 +86,20 @@ public Response post(@FormDataParam("file") InputStream fileInputStream, /** * Retrieves a temp file by fileId + * + * @param fileId + * @return Response with temporary file */ @GET @Path("tmp/{fileId}") - public Response getTmpFile(@PathParam("fileId") String fileId) { - File tmpFile = Paths.get(Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY), fileId).toFile(); - if (tmpFile == null || !tmpFile.exists()) + public Response getTmpFile(@PathParam("fileId") final String fileId) { + final File tmpFile = Paths.get(Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY), + fileId).toFile(); + if (tmpFile == null || !tmpFile.exists()) { return super.respond(Response.Status.NOT_FOUND); + } - Response.ResponseBuilder response = Response.ok(tmpFile); + final Response.ResponseBuilder response = Response.ok(tmpFile); if (tmpFile.getName().endsWith(".csv")) { response.header("Content-Type", "text/csv; name=\"" + tmpFile.getName() + "\""); } @@ -86,211 +107,244 @@ public Response getTmpFile(@PathParam("fileId") String fileId) { return response.build(); } + /** + * @param fileId + * @return Response with attachment + */ @GET @Path("attachment/{fileId}") - public Response getAttachment(@PathParam("fileId") String fileId, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response getAttachment(@PathParam("fileId") final String fileId) { try { - if (StringUtils.isEmpty(sessionId)) - sessionId = sid; - - String userId = getUserIdFromSessionHeader(sessionId); - File file = attachmentController.getAttachmentByFileId(userId, fileId); - if (file == null) + final String userId = getUserId(); + final File file = attachmentController.getAttachmentByFileId(userId, fileId); + if (file == null) { return respond(Response.Status.NOT_FOUND); + } - String name = DAOFactory.getAttachmentDAO().getByFileId(fileId).getFileName(); - Response.ResponseBuilder response = Response.ok(file); + final String name = DAOFactory.getAttachmentDAO().getByFileId(fileId).getFileName(); + final Response.ResponseBuilder response = Response.ok(file); response.header("Content-Disposition", "attachment; filename=\"" + name + "\""); return response.build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } + /** + * @param partnerId + * @param fileId + * @return Response with remote attachment file + */ @GET @Path("remote/{id}/attachment/{fileId}") - public Response getRemoteAttachment(@PathParam("id") long partnerId, - @PathParam("fileId") String fileId, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response getRemoteAttachment(@PathParam("id") final long partnerId, + @PathParam("fileId") final String fileId) { try { - RemoteAccessController controller = new RemoteAccessController(); - File file = controller.getPublicAttachment(partnerId, fileId); - if (file == null) + final RemoteAccessController controller = new RemoteAccessController(); + final File file = controller.getPublicAttachment(partnerId, fileId); + if (file == null) { return respond(Response.Status.NOT_FOUND); + } - Response.ResponseBuilder response = Response.ok(file); + final Response.ResponseBuilder response = Response.ok(file); response.header("Content-Disposition", "attachment; filename=\"remoteAttachment\""); return response.build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } + /** + * @param type + * @param linkedType + * @return Response with upload CSV file + */ @GET @Path("upload/{type}") - public Response getUploadCSV(@PathParam("type") String type, @QueryParam("link") String linkedType) { + public Response getUploadCSV(@PathParam("type") final String type, + @QueryParam("link") final String linkedType) { final EntryType entryAddType = EntryType.nameToType(type); final EntryType linked; - if (linkedType != null) + if (linkedType != null) { linked = EntryType.nameToType(linkedType); - else + } else { linked = null; + } - StreamingOutput stream = new StreamingOutput() { + final StreamingOutput stream = new StreamingOutput() { @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - byte[] template = FileBulkUpload.getCSVTemplateBytes(entryAddType, linked); - ByteArrayInputStream stream = new ByteArrayInputStream(template); + public void write(final OutputStream output) throws IOException, + WebApplicationException { + final byte[] template = FileBulkUpload.getCSVTemplateBytes(entryAddType, linked); + final ByteArrayInputStream stream = new ByteArrayInputStream(template); IOUtils.copy(stream, output); } }; String filename = type.toLowerCase(); - if (linkedType != null) + if (linkedType != null) { filename += ("_" + linkedType.toLowerCase()); + } - return Response.ok(stream).header("Content-Disposition", "attachment;filename=" - + filename + "_csv_upload.csv").build(); + return Response + .ok(stream) + .header("Content-Disposition", + "attachment;filename=" + filename + "_csv_upload.csv").build(); } + /** + * @param partId + * @param downloadType + * @return Response with sequence file + */ @GET @Path("{partId}/sequence/{type}") - public Response downloadSequence( - @PathParam("partId") final long partId, - @PathParam("type") final String downloadType, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { - if (StringUtils.isEmpty(sessionId)) - sessionId = sid; - - final String userId = getUserIdFromSessionHeader(sessionId); - final ByteArrayWrapper wrapper = sequenceController.getSequenceFile(userId, partId, downloadType); + public Response downloadSequence(@PathParam("partId") final long partId, + @PathParam("type") final String downloadType) { + final String userId = getUserId(); + final ByteArrayWrapper wrapper = sequenceController.getSequenceFile(userId, partId, + downloadType); - StreamingOutput stream = new StreamingOutput() { + final StreamingOutput stream = new StreamingOutput() { @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - ByteArrayInputStream stream = new ByteArrayInputStream(wrapper.getBytes()); + public void write(final OutputStream output) throws IOException, + WebApplicationException { + final ByteArrayInputStream stream = new ByteArrayInputStream(wrapper.getBytes()); IOUtils.copy(stream, output); } }; - return Response.ok(stream).header("Content-Disposition", "attachment;filename=" + wrapper.getName()).build(); + return Response.ok(stream) + .header("Content-Disposition", "attachment;filename=" + wrapper.getName()).build(); } + /** + * @param fileId + * @return Response with sequence file + */ @GET @Path("trace/{fileId}") - public Response getTraceSequenceFile(@PathParam("fileId") String fileId, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response getTraceSequenceFile(@PathParam("fileId") final String fileId) { try { - SequenceAnalysisController sequenceAnalysisController = new SequenceAnalysisController(); - TraceSequence traceSequence = sequenceAnalysisController.getTraceSequenceByFileId(fileId); + final SequenceAnalysisController sequenceAnalysisController = new SequenceAnalysisController(); + final TraceSequence traceSequence = sequenceAnalysisController + .getTraceSequenceByFileId(fileId); if (traceSequence != null) { - File file = sequenceAnalysisController.getFile(traceSequence); - Response.ResponseBuilder response = Response.ok(file); - response.header("Content-Disposition", "attachment; filename=\"" + traceSequence.getFilename() + "\""); + final File file = sequenceAnalysisController.getFile(traceSequence); + final Response.ResponseBuilder response = Response.ok(file); + response.header("Content-Disposition", + "attachment; filename=\"" + traceSequence.getFilename() + "\""); return response.build(); } return Response.serverError().build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.serverError().build(); } } + /** + * @param recordId + * @return Response with image file for the SBOL + */ @GET @Produces("image/png") @Path("sbolVisual/{rid}") - public Response getSBOLVisual(@PathParam("rid") String recordId, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response getSBOLVisual(@PathParam("rid") final String recordId) { try { - String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); - Entry entry = DAOFactory.getEntryDAO().getByRecordId(recordId); - Sequence sequence = entry.getSequence(); - String hash = sequence.getFwdHash(); - String fileId; - - if (Paths.get(tmpDir, hash + ".png").toFile().exists()) { - fileId = (hash + ".png"); - File file = Paths.get(tmpDir, fileId).toFile(); + final String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); + final Entry entry = DAOFactory.getEntryDAO().getByRecordId(recordId); + final Sequence sequence = entry.getSequence(); + final String hash = sequence.getFwdHash(); + final File png = Paths.get(tmpDir, hash + ".png").toFile(); - Response.ResponseBuilder response = Response.ok(file); - response.header("Content-Disposition", "attachment; filename=" + entry.getPartNumber() + ".png"); + if (png.exists()) { + final Response.ResponseBuilder response = Response.ok(png); + response.header("Content-Disposition", + "attachment; filename=" + entry.getPartNumber() + ".png"); return response.build(); - } else { - URI uri = PigeonSBOLv.generatePigeonVisual(sequence); - if (uri != null) { - IOUtils.copy(uri.toURL().openStream(), - new FileOutputStream(tmpDir + File.separatorChar + hash + ".png")); - fileId = (hash + ".png"); - File file = Paths.get(tmpDir, fileId).toFile(); - - Response.ResponseBuilder response = Response.ok(file); - response.header("Content-Disposition", "attachment; filename=" + entry.getPartNumber() + ".png"); - return response.build(); + } + final URI uri = PigeonSBOLv.generatePigeonVisual(sequence); + if (uri != null) { + try (final InputStream in = uri.toURL().openStream(); + final OutputStream out = new FileOutputStream(png);) { + IOUtils.copy(in, out); } + final Response.ResponseBuilder response = Response.ok(png); + response.header("Content-Disposition", + "attachment; filename=" + entry.getPartNumber() + ".png"); + return response.build(); } - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return null; } return null; } - // this creates an entry if an id is not specified in the form data + /** + * this creates an entry if an id is not specified in the form data + * + * @param fileInputStream + * @param recordId + * @param entryType + * @param contentDispositionHeader + * @return Response containing sequence info + */ @POST @Path("sequence") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response uploadSequence(@FormDataParam("file") InputStream fileInputStream, - @FormDataParam("entryRecordId") String recordId, - @FormDataParam("entryType") String entryType, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response uploadSequence(@FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("entryRecordId") final String recordId, + @FormDataParam("entryType") final String entryType, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - if (entryType == null) + if (entryType == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } - String fileName = contentDispositionHeader.getFileName(); - String userId = SessionHandler.getUserIdBySession(sessionId); - String sequence = IOUtils.toString(fileInputStream); - SequenceInfo sequenceInfo = sequenceController.parseSequence(userId, recordId, entryType, sequence, - fileName); - if (sequenceInfo == null) + final String fileName = contentDispositionHeader.getFileName(); + final String userId = getUserId(); + final String sequence = IOUtils.toString(fileInputStream); + final SequenceInfo sequenceInfo = sequenceController.parseSequence(userId, recordId, + entryType, sequence, fileName); + if (sequenceInfo == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(Response.Status.OK).entity(sequenceInfo).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } /** - * Extracts the csv information and writes it to the temp dir and returns the file uuid. - * Then the client is expected to make another rest call with the uuid is a separate window. - * This workaround is due to not being able to download files using XHR or sumsuch + * Extracts the csv information and writes it to the temp dir and returns the file uuid. Then + * the client is expected to make another rest call with the uuid is a separate window. This + * workaround is due to not being able to download files using XHR or sumsuch + * + * @param selection + * @return Response with filename wrapped in a Setting object */ @POST @Path("csv") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response downloadCSV( - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId, - EntrySelection selection) { - String userId = super.getUserIdFromSessionHeader(sessionId); - EntriesAsCSV entriesAsCSV = new EntriesAsCSV(); - boolean success = entriesAsCSV.setSelectedEntries(userId, selection); - if (!success) + public Response downloadCSV(final EntrySelection selection) { + final String userId = getUserId(); + final EntriesAsCSV entriesAsCSV = new EntriesAsCSV(); + final boolean success = entriesAsCSV.setSelectedEntries(userId, selection); + if (!success) { return super.respond(false); + } - File file = entriesAsCSV.getFilePath().toFile(); - if (file.exists()) + final File file = entriesAsCSV.getFilePath().toFile(); + if (file.exists()) { return Response.ok(new Setting("key", file.getName())).build(); + } return respond(false); } } From bddcae84e6f04db55b8518ced32825c32a9be1d1 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 2 Apr 2015 17:44:16 -0700 Subject: [PATCH 04/67] Converting more resources; PartResource sometimes needs to authenticate via query parameter, added support to RestResource to handle these cases --- .../ice/services/rest/FolderResource.java | 326 ++++++---- .../jbei/ice/services/rest/GroupResource.java | 37 +- .../ice/services/rest/MessageResource.java | 14 +- .../jbei/ice/services/rest/PartResource.java | 603 +++++++++++------- .../jbei/ice/services/rest/RestResource.java | 27 + 5 files changed, 619 insertions(+), 388 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/FolderResource.java b/src/main/java/org/jbei/ice/services/rest/FolderResource.java index 86d38f7a7..73960616e 100644 --- a/src/main/java/org/jbei/ice/services/rest/FolderResource.java +++ b/src/main/java/org/jbei/ice/services/rest/FolderResource.java @@ -1,7 +1,24 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.jbei.ice.lib.access.PermissionsController; -import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.entry.PartData; import org.jbei.ice.lib.dto.folder.FolderDetails; @@ -15,14 +32,6 @@ import org.jbei.ice.lib.folder.FolderController; import org.jbei.ice.lib.shared.ColumnField; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; -import java.util.List; - /** * @author Hector Plahar */ @@ -33,120 +42,151 @@ public class FolderResource extends RestResource { private FolderContentRetriever retriever = new FolderContentRetriever(); private PermissionsController permissionsController = new PermissionsController(); + /** + * @return all collections visible to current user + */ @GET @Produces(MediaType.APPLICATION_JSON) - public Collection retrieveCollection( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String sid = getUserIdFromSessionHeader(userAgentHeader); + public Collection retrieveCollection() { + final String sid = getUserId(); return controller.getFolderStats(sid); } + /** + * @param folder + * @return Response with info on created folder + */ @PUT @Produces(MediaType.APPLICATION_JSON) - public FolderDetails create( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - FolderDetails folder) { - String sid = getUserIdFromSessionHeader(userAgentHeader); + public FolderDetails create(final FolderDetails folder) { + final String sid = getUserId(); return controller.createPersonalFolder(sid, folder); } - // TODO : allow api key as well + /** + * TODO allow api key as well + * + * @return all public collections + */ @GET @Path("/public") @Produces(MediaType.APPLICATION_JSON) - public ArrayList getPublicFolders( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public ArrayList getPublicFolders() { return controller.getPublicFolders(); } + /** + * @param folderType + * @return all collections of a type + */ @GET @Path("/{type}") @Produces(MediaType.APPLICATION_JSON) public ArrayList getSubFolders( - @DefaultValue("personal") @PathParam("type") String folderType, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String sid = getUserIdFromSessionHeader(userAgentHeader); + @DefaultValue("personal") @PathParam("type") final String folderType) { + final String sid = getUserId(); switch (folderType) { - case "personal": - return controller.getUserFolders(sid); + case "personal": + return controller.getUserFolders(sid); - case "available": - return controller.getAvailableFolders(sid); + case "available": + return controller.getAvailableFolders(sid); - case "drafts": - return controller.getBulkUploadDrafts(sid); + case "drafts": + return controller.getBulkUploadDrafts(sid); - case "pending": - return controller.getPendingBulkUploads(sid); + case "pending": + return controller.getPendingBulkUploads(sid); - case "shared": - return controller.getSharedUserFolders(sid); + case "shared": + return controller.getSharedUserFolders(sid); - default: - return new ArrayList<>(); + default: + return new ArrayList<>(); } } + /** + * @param folderId + * @param details + * @return Response with updated collection info + */ @PUT @Path("/{id}") - public Response update(@PathParam("id") long folderId, - FolderDetails details, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - FolderDetails resp = controller.update(userId, folderId, details); + public Response update(@PathParam("id") final long folderId, final FolderDetails details) { + final String userId = getUserId(); + final FolderDetails resp = controller.update(userId, folderId, details); return super.respond(Response.Status.OK, resp); } + /** + * @param folderId + * @param folderType + * @return the details of the deleted collection + */ @DELETE @Path("/{id}") - public FolderDetails deleteFolder(@PathParam("id") long folderId, - @QueryParam("type") String folderType, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - FolderType type = FolderType.valueOf(folderType); + public FolderDetails deleteFolder(@PathParam("id") final long folderId, + @QueryParam("type") final String folderType) { + final String userId = getUserId(); + final FolderType type = FolderType.valueOf(folderType); return controller.delete(userId, folderId, type); } + /** + * @param entrySelection + * @return Response with updated collection details + */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/transfer") - public Response addSelectedEntriesToFolder( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - EntrySelection entrySelection) { - String userId = getUserIdFromSessionHeader(sessionId); - FolderContent folderContent = new FolderContent(); - List result = folderContent.addEntrySelection(userId, entrySelection); + public Response addSelectedEntriesToFolder(final EntrySelection entrySelection) { + final String userId = getUserId(); + final FolderContent folderContent = new FolderContent(); + final List result = folderContent.addEntrySelection(userId, entrySelection); return super.respond(result); } + /** + * @param entrySelection + * @param folderId + * @return Response indicating success or failure + */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") - public Response removeEntriesFromFolder( - EntrySelection entrySelection, - @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.removeFolderContents(userId, folderId, entrySelection)) + public Response removeEntriesFromFolder(final EntrySelection entrySelection, + @PathParam("id") final long folderId) { + final String userId = getUserId(); + if (controller.removeFolderContents(userId, folderId, entrySelection)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param uriInfo + * @param folderId + * @param offset + * @param limit + * @param sort + * @param asc + * @return details of the selected collection + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") - public FolderDetails read(@Context UriInfo uriInfo, - @PathParam("id") String folderId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public FolderDetails read(@Context final UriInfo uriInfo, + @PathParam("id") final String folderId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { - ColumnField field = ColumnField.valueOf(sort.toUpperCase()); + final ColumnField field = ColumnField.valueOf(sort.toUpperCase()); if (folderId.equalsIgnoreCase("public")) { // return public entries @@ -154,118 +194,148 @@ public FolderDetails read(@Context UriInfo uriInfo, return controller.getPublicEntries(field, offset, limit, asc); } - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + final String userId = getUserId(); try { - long id = Long.decode(folderId); + final long id = Long.decode(folderId); Logger.info("Retrieving folder " + id + " entries"); return controller.retrieveFolderContents(userId, id, field, asc, offset, limit); - } catch (NumberFormatException nfe) { + } catch (final NumberFormatException nfe) { } - EntryController entryController = new EntryController(); - FolderDetails details = new FolderDetails(); + final EntryController entryController = new EntryController(); + final FolderDetails details = new FolderDetails(); log(userId, "retrieving " + folderId + " entries"); switch (folderId) { - case "personal": - List entries = entryController.retrieveOwnerEntries(userId, userId, field, - asc, offset, limit); - long count = entryController.getNumberOfOwnerEntries(userId, userId); - details.getEntries().addAll(entries); - details.setCount(count); - return details; - - case "available": - FolderDetails retrieved = entryController.retrieveVisibleEntries(userId, field, asc, offset, limit); - details.setEntries(retrieved.getEntries()); - details.setCount(entryController.getNumberOfVisibleEntries(userId)); - return details; - - case "shared": - List data = entryController.getEntriesSharedWithUser(userId, field, asc, offset, limit); - details.setEntries(data); - details.setCount(entryController.getNumberOfEntriesSharedWithUser(userId)); - return details; - - case "drafts": - return retriever.getDraftEntries(userId, field, asc, offset, limit); - - case "deleted": - return retriever.getDeletedEntries(userId, field, asc, offset, limit); - - case "pending": - return retriever.getPendingEntries(userId, field, asc, offset, limit); - - case "transferred": - return retriever.getTransferredEntries(userId, field, asc, offset, limit); - - default: - return null; + case "personal": + final List entries = entryController.retrieveOwnerEntries(userId, userId, + field, asc, offset, limit); + final long count = entryController.getNumberOfOwnerEntries(userId, userId); + details.getEntries().addAll(entries); + details.setCount(count); + return details; + + case "available": + final FolderDetails retrieved = entryController.retrieveVisibleEntries(userId, field, + asc, offset, limit); + details.setEntries(retrieved.getEntries()); + details.setCount(entryController.getNumberOfVisibleEntries(userId)); + return details; + + case "shared": + final List data = entryController.getEntriesSharedWithUser(userId, field, + asc, offset, limit); + details.setEntries(data); + details.setCount(entryController.getNumberOfEntriesSharedWithUser(userId)); + return details; + + case "drafts": + return retriever.getDraftEntries(userId, field, asc, offset, limit); + + case "deleted": + return retriever.getDeletedEntries(userId, field, asc, offset, limit); + + case "pending": + return retriever.getPendingEntries(userId, field, asc, offset, limit); + + case "transferred": + return retriever.getTransferredEntries(userId, field, asc, offset, limit); + + default: + return null; } } + /** + * @param folderId + * @return Response with permissions on a collection + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public Response getFolderPermissions( - @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response getFolderPermissions(@PathParam("id") final long folderId) { + final String userId = getUserId(); return respond(controller.getPermissions(userId, folderId)); } + /** + * @param info + * @param folderId + * @param permissions + * @return details of the modified collection + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public FolderDetails setPermissions(@Context UriInfo info, @PathParam("id") long folderId, - ArrayList permissions, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public FolderDetails setPermissions(@Context final UriInfo info, + @PathParam("id") final long folderId, final ArrayList permissions) { + final String userId = getUserId(); return permissionsController.setFolderPermissions(userId, folderId, permissions); } + /** + * @param info + * @param folderId + * @param permission + * @return the added permission + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public AccessPermission addPermission(@Context UriInfo info, @PathParam("id") long folderId, - AccessPermission permission, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public AccessPermission addPermission(@Context final UriInfo info, + @PathParam("id") final long folderId, final AccessPermission permission) { + final String userId = getUserId(); return controller.createFolderPermission(userId, folderId, permission); } + /** + * @param info + * @param partId + * @param permissionId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/{permissionId}") - public Response removePermission(@Context UriInfo info, - @PathParam("id") long partId, - @PathParam("permissionId") long permissionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response removePermission(@Context final UriInfo info, + @PathParam("id") final long partId, @PathParam("permissionId") final long permissionId) { + final String userId = getUserId(); permissionsController.removeFolderPermission(userId, partId, permissionId); return Response.ok().build(); } + /** + * @param info + * @param folderId + * @return Response for success or failure + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response enablePublicAccess(@Context UriInfo info, @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (controller.enablePublicReadAccess(userId, folderId)) + public Response enablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long folderId) { + final String userId = getUserId(); + if (controller.enablePublicReadAccess(userId, folderId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param info + * @param folderId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response disablePublicAccess(@Context UriInfo info, @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (controller.disablePublicReadAccess(userId, folderId)) + public Response disablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long folderId) { + final String userId = getUserId(); + if (controller.disablePublicReadAccess(userId, folderId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } } diff --git a/src/main/java/org/jbei/ice/services/rest/GroupResource.java b/src/main/java/org/jbei/ice/services/rest/GroupResource.java index 854fde4be..e8df5afdb 100644 --- a/src/main/java/org/jbei/ice/services/rest/GroupResource.java +++ b/src/main/java/org/jbei/ice/services/rest/GroupResource.java @@ -1,8 +1,8 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; + import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -22,34 +22,43 @@ public class GroupResource extends RestResource { private GroupController groupController = new GroupController(); + /** + * @param id + * @return Response with group info + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public Response getGroup(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - UserGroup group = groupController.getGroupById(userId, id); + public Response getGroup(@PathParam("id") final long id) { + final String userId = getUserId(); + final UserGroup group = groupController.getGroupById(userId, id); return respond(group); } + /** + * @param id + * @return Response with group members + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/members") - public Response getGroupMembers(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - ArrayList members = groupController.getGroupMembers(userId, id); + public Response getGroupMembers(@PathParam("id") final long id) { + final String userId = getUserId(); + final ArrayList members = groupController.getGroupMembers(userId, id); return respond(members); } + /** + * @param id + * @param group + * @return response with success or failure + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public Response updateGroup(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - UserGroup group) { - String userId = getUserIdFromSessionHeader(sessionId); - boolean success = groupController.updateGroup(userId, group); + public Response updateGroup(@PathParam("id") final long id, final UserGroup group) { + final String userId = getUserId(); + final boolean success = groupController.updateGroup(userId, group); return respond(success); } } diff --git a/src/main/java/org/jbei/ice/services/rest/MessageResource.java b/src/main/java/org/jbei/ice/services/rest/MessageResource.java index 2e5546d02..b069882d0 100644 --- a/src/main/java/org/jbei/ice/services/rest/MessageResource.java +++ b/src/main/java/org/jbei/ice/services/rest/MessageResource.java @@ -2,7 +2,6 @@ import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; @@ -20,13 +19,16 @@ public class MessageResource extends RestResource { private MessageController controller = new MessageController(); + /** + * @param offset + * @param limit + * @return list of messages + */ @GET @Produces(MediaType.APPLICATION_JSON) - public MessageList get( - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public MessageList get(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit) { + final String userId = getUserId(); Logger.info(userId + ": retrieving available messages"); return controller.retrieveMessages(userId, userId, offset, limit); } diff --git a/src/main/java/org/jbei/ice/services/rest/PartResource.java b/src/main/java/org/jbei/ice/services/rest/PartResource.java index d688ab33d..b07d10229 100644 --- a/src/main/java/org/jbei/ice/services/rest/PartResource.java +++ b/src/main/java/org/jbei/ice/services/rest/PartResource.java @@ -1,20 +1,48 @@ package org.jbei.ice.services.rest; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + import org.jbei.ice.lib.access.PermissionException; import org.jbei.ice.lib.access.PermissionsController; -import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.ConfigurationKey; import org.jbei.ice.lib.dto.History; import org.jbei.ice.lib.dto.comment.UserComment; -import org.jbei.ice.lib.dto.entry.*; +import org.jbei.ice.lib.dto.entry.AttachmentInfo; +import org.jbei.ice.lib.dto.entry.AutoCompleteField; +import org.jbei.ice.lib.dto.entry.EntryType; +import org.jbei.ice.lib.dto.entry.PartData; +import org.jbei.ice.lib.dto.entry.PartStatistics; +import org.jbei.ice.lib.dto.entry.TraceSequenceAnalysis; import org.jbei.ice.lib.dto.permission.AccessPermission; import org.jbei.ice.lib.dto.sample.PartSample; import org.jbei.ice.lib.entry.EntryController; @@ -28,19 +56,6 @@ import org.jbei.ice.lib.utils.Utils; import org.jbei.ice.lib.vo.FeaturedDNASequence; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Type; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Set; - /** * @author Hector Plahar */ @@ -55,484 +70,592 @@ public class PartResource extends RestResource { private ExperimentController experimentController = new ExperimentController(); private SampleController sampleController = new SampleController(); + /** + * @param val + * @param field + * @param limit + * @return list of autocomplete values for a field + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") - public ArrayList autoComplete(@QueryParam("val") String val, - @DefaultValue("SELECTION_MARKERS") @QueryParam("field") String field, - @DefaultValue("8") @QueryParam("limit") int limit) { - AutoCompleteField autoCompleteField = AutoCompleteField.valueOf(field.toUpperCase()); - Set result = retriever.getMatchingAutoCompleteField(autoCompleteField, val, limit); + public ArrayList autoComplete(@QueryParam("val") final String val, + @DefaultValue("SELECTION_MARKERS") @QueryParam("field") final String field, + @DefaultValue("8") @QueryParam("limit") final int limit) { + final AutoCompleteField autoCompleteField = AutoCompleteField.valueOf(field.toUpperCase()); + final Set result = retriever.getMatchingAutoCompleteField(autoCompleteField, val, + limit); return new ArrayList<>(result); } + /** + * @param token + * @param limit + * @return list of autocomplete values for parts + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete/partid") - public ArrayList autoComplete(@QueryParam("token") String token, - @DefaultValue("8") @QueryParam("limit") int limit) { + public ArrayList autoComplete(@QueryParam("token") final String token, + @DefaultValue("8") @QueryParam("limit") final int limit) { return retriever.getMatchingPartNumber(token, limit); } /** - * Retrieves a part using any of the unique identifiers. e.g. Part number, synthetic id, or global unique - * identifier + * Retrieves a part using any of the unique identifiers. e.g. Part number, synthetic id, or + * global unique identifier * * @param info * @param id - * @param sessionId unique session identifier - * @return + * @return Response with part data */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public Response read(@Context UriInfo info, - @PathParam("id") String id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = SessionHandler.getUserIdBySession(sessionId); + public Response read(@Context final UriInfo info, @PathParam("id") final String id) { + final String userId = getUserId(); try { log(userId, "retrieving details for " + id); - EntryType type = EntryType.nameToType(id); + final EntryType type = EntryType.nameToType(id); PartData data; - if (type != null) + if (type != null) { data = controller.getPartDefaults(userId, type); - else + } else { data = controller.retrieveEntryDetails(userId, id); + } return super.respond(data); - } catch (PermissionException pe) { + } catch (final PermissionException pe) { // todo : have a generic error entity returned return Response.status(Response.Status.FORBIDDEN).build(); } } /** - * Retrieves a comma separated value representation of the part referenced by the path parameter identifier - */ -// @GET -// @Produces(MediaType.APPLICATION_JSON) -// @Path("/{id}/csv") -// public Response getCSV( -// @PathParam("id") String id, -// @QueryParam("sid") String sid, -// @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { -// if (StringUtils.isEmpty(sessionId)) -// sessionId = sid; -// -// String userId = getUserIdFromSessionHeader(sessionId); -// log(userId, "retrieving part csv"); -// String csv = null; // retriever.getAsCSV(userId, id); -// if (csv != null) { -// String name = retriever.getPartNumber(userId, id); -// if (name == null) -// name = "entry.csv"; -// else -// name += ".csv"; -// Response.ResponseBuilder response = Response.ok(csv); -// response.header("Content-Disposition", "attachment; filename=\"" + name + "\""); -// return response.build(); -// } -// return Response.status(Response.Status.NOT_FOUND).build(); -// } - + * @param id + * @return part data with tooltip information + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/tooltip") - public PartData getTooltipDetails(@PathParam("id") String id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public PartData getTooltipDetails(@PathParam("id") final String id) { + final String userId = getUserId(); return controller.retrieveEntryTipDetails(userId, id); } + /** + * @param info + * @param id + * @return permissions on the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public ArrayList getPermissions(@Context UriInfo info, @PathParam("id") String id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList getPermissions(@Context final UriInfo info, + @PathParam("id") final String id) { + final String userId = getUserId(); return retriever.getEntryPermissions(userId, id); } + /** + * @param info + * @param partId + * @param permissions + * @return part data with permission information + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public PartData setPermissions(@Context UriInfo info, @PathParam("id") long partId, - ArrayList permissions, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public PartData setPermissions(@Context final UriInfo info, @PathParam("id") final long partId, + final ArrayList permissions) { + final String userId = getUserId(); return permissionsController.setEntryPermissions(userId, partId, permissions); } + /** + * @param partId + * @return Response with studies on a part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/experiments") - public Response getPartExperiments(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - ArrayList studies = experimentController.getPartStudies(userId, partId); - if (studies == null) + public Response getPartExperiments(@PathParam("id") final long partId) { + final String userId = getUserId(); + final ArrayList studies = experimentController.getPartStudies(userId, partId); + if (studies == null) { return respond(Response.Status.INTERNAL_SERVER_ERROR); + } return respond(Response.Status.OK, studies); } + /** + * @param partId + * @param study + * @return response with study information + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/experiments") - public Response getPartExperiments(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - Study study) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - study = experimentController.createStudy(userId, partId, study); - return respond(Response.Status.OK, study); + public Response getPartExperiments(@PathParam("id") final long partId, final Study study) { + final String userId = getUserId(); + final Study created = experimentController.createStudy(userId, partId, study); + return respond(Response.Status.OK, created); } + /** + * @param info + * @param partId + * @return Response for success or failure + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response enablePublicAccess(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (permissionsController.enablePublicReadAccess(userId, partId)) + public Response enablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); + if (permissionsController.enablePublicReadAccess(userId, partId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param info + * @param partId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response disablePublicAccess(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (permissionsController.disablePublicReadAccess(userId, partId)) + public Response disablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); + if (permissionsController.disablePublicReadAccess(userId, partId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param info + * @param partId + * @param permission + * @return the created permission + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public AccessPermission createPermission(@Context UriInfo info, @PathParam("id") long partId, - AccessPermission permission, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public AccessPermission createPermission(@Context final UriInfo info, + @PathParam("id") final long partId, final AccessPermission permission) { + final String userId = getUserId(); return permissionsController.createPermission(userId, partId, permission); } + /** + * @param info + * @param partId + * @param permissionId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/{permissionId}") - public Response removePermission(@Context UriInfo info, - @PathParam("id") long partId, - @PathParam("permissionId") long permissionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response removePermission(@Context final UriInfo info, + @PathParam("id") final long partId, @PathParam("permissionId") final long permissionId) { + final String userId = getUserId(); permissionsController.removeEntryPermission(userId, partId, permissionId); return Response.ok().build(); } + /** + * @param partId + * @return statistics on part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/statistics") - public PartStatistics getStatistics(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public PartStatistics getStatistics(@PathParam("id") final long partId) { + final String userId = getUserId(); return controller.retrieveEntryStatistics(userId, partId); } + /** + * @param info + * @param partId + * @return comments on part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/comments") - public ArrayList getComments(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public ArrayList getComments(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); return controller.retrieveEntryComments(userId, partId); } + /** + * @param partId + * @param userComment + * @return the created comment + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/comments") - public Response createComment(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - UserComment userComment) { -// if(userComment == null || userComment.getMessage() == null) -// throw new Web + public Response createComment(@PathParam("id") final long partId, final UserComment userComment) { // todo : check for null - String userId = getUserIdFromSessionHeader(userAgentHeader); + final String userId = getUserId(); log(userId, "adding comment to entry " + partId); - UserComment comment = controller.createEntryComment(userId, partId, userComment); + final UserComment comment = controller.createEntryComment(userId, partId, userComment); return respond(comment); } + /** + * @param partId + * @param commentId + * @param userComment + * @return the updated comment + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/comments/{commentId}") - public UserComment updateComment(@PathParam("id") long partId, - @PathParam("commentId") long commentId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - UserComment userComment) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public UserComment updateComment(@PathParam("id") final long partId, + @PathParam("commentId") final long commentId, final UserComment userComment) { + final String userId = getUserId(); return controller.updateEntryComment(userId, partId, commentId, userComment); } + /** + * @param partId + * @param attachment + * @return created attachment info + */ @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Path("/{id}/attachments") - public AttachmentInfo addAttachment(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - AttachmentInfo attachment) { + public AttachmentInfo addAttachment(@PathParam("id") final long partId, + final AttachmentInfo attachment) { // todo : check for null - String userId = getUserIdFromSessionHeader(userAgentHeader); - AttachmentController attachmentController = new AttachmentController(); + final String userId = getUserId(); + final AttachmentController attachmentController = new AttachmentController(); return attachmentController.addAttachmentToEntry(userId, partId, attachment); } + /** + * @param partId + * @return all attachments on a part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/attachments") - public ArrayList getAttachments(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public ArrayList getAttachments(@PathParam("id") final long partId) { + final String userId = getUserId(); return attachmentController.getByEntry(userId, partId); } + /** + * @param info + * @param partId + * @param attachmentId + * @return A response for success or failure + */ @DELETE @Path("/{id}/attachments/{attachmentId}") - public Response deleteAttachment(@Context UriInfo info, - @PathParam("id") long partId, - @PathParam("attachmentId") long attachmentId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (!attachmentController.delete(userId, partId, attachmentId)) + public Response deleteAttachment(@Context final UriInfo info, + @PathParam("id") final long partId, @PathParam("attachmentId") final long attachmentId) { + final String userId = getUserId(); + if (!attachmentController.delete(userId, partId, attachmentId)) { return Response.notModified().build(); // todo : use 404 ? + } return Response.ok().build(); } + /** + * @param info + * @param partId + * @param sessionId + * @return history entries for the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/history") - public ArrayList getHistory(@Context UriInfo info, - @PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - String userId = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList getHistory(@Context final UriInfo info, + @PathParam("id") final long partId, @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); return controller.getHistory(userId, partId); } + /** + * @param partId + * @param historyId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/history/{historyId}") - public Response delete(@PathParam("id") long partId, - @PathParam("historyId") long historyId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - boolean success = controller.deleteHistory(userId, partId, historyId); + public Response delete(@PathParam("id") final long partId, + @PathParam("historyId") final long historyId) { + final String userId = getUserId(); + final boolean success = controller.deleteHistory(userId, partId, historyId); return super.respond(success); } + /** + * @param info + * @param partId + * @param sessionId + * @return traces for the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/traces") - public ArrayList getTraces(@Context UriInfo info, - @PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public ArrayList getTraces(@Context final UriInfo info, + @PathParam("id") final long partId, @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); return controller.getTraceSequences(userId, partId); } + /** + * @param partId + * @param fileInputStream + * @param contentDispositionHeader + * @param sessionId + * @return Response for success or failure + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/traces") - public Response addTraceSequence(@PathParam("id") long partId, - @FormDataParam("file") InputStream fileInputStream, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - String userId = getUserIdFromSessionHeader(userAgentHeader); - String fileName = contentDispositionHeader.getFileName(); - String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); - File file = Paths.get(tmpDir, fileName).toFile(); + public Response addTraceSequence(@PathParam("id") final long partId, + @FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, + @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); + final String fileName = contentDispositionHeader.getFileName(); + final String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); + final File file = Paths.get(tmpDir, fileName).toFile(); try { FileUtils.copyInputStreamToFile(fileInputStream, file); - } catch (IOException e) { + } catch (final IOException e) { Logger.error(e); return respond(Response.Status.INTERNAL_SERVER_ERROR); } - boolean success = controller.addTraceSequence(userId, partId, file, fileName); + final boolean success = controller.addTraceSequence(userId, partId, file, fileName); return respond(success); } + /** + * @param info + * @param partId + * @param traceId + * @return Response for success or failure + */ @DELETE @Path("/{id}/traces/{traceId}") - public Response deleteTrace(@Context UriInfo info, @PathParam("id") long partId, - @PathParam("traceId") long traceId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (!controller.deleteTraceSequence(userId, partId, traceId)) + public Response deleteTrace(@Context final UriInfo info, @PathParam("id") final long partId, + @PathParam("traceId") final long traceId) { + final String userId = getUserId(); + if (!controller.deleteTraceSequence(userId, partId, traceId)) { return super.respond(Response.Status.UNAUTHORIZED); + } return super.respond(Response.Status.OK); } + /** + * @param info + * @param partId + * @return samples on the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples") - public ArrayList getSamples(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public ArrayList getSamples(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); return sampleController.retrieveEntrySamples(userId, partId); } + /** + * @param info + * @param partId + * @param strainNamePrefix + * @param partSample + * @return all samples on a part + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples") - public ArrayList addSample(@Context UriInfo info, @PathParam("id") long partId, - @QueryParam("strainNamePrefix") String strainNamePrefix, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - PartSample partSample) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public ArrayList addSample(@Context final UriInfo info, + @PathParam("id") final long partId, + @QueryParam("strainNamePrefix") final String strainNamePrefix, + final PartSample partSample) { + final String userId = getUserId(); log(userId, "creating sample for part " + partId); sampleController.createSample(userId, partId, partSample, strainNamePrefix); return sampleController.retrieveEntrySamples(userId, partId); } + /** + * @param info + * @param partId + * @param sampleId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples/{sampleId}") - public Response deleteSample(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @PathParam("sampleId") long sampleId) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); - boolean success = sampleController.delete(userId, partId, sampleId); + public Response deleteSample(@Context final UriInfo info, @PathParam("id") final long partId, + @PathParam("sampleId") final long sampleId) { + final String userId = getUserId(); + final boolean success = sampleController.delete(userId, partId, sampleId); return super.respond(success); } + /** + * @param partId + * @param sessionId + * @return Response with the part sequence + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/sequence") - public Response getSequence(@PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - - String userId = SessionHandler.getUserIdBySession(userAgentHeader); - FeaturedDNASequence sequence = sequenceController.retrievePartSequence(userId, partId); - if (sequence == null) + public Response getSequence(@PathParam("id") final long partId, + @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); + final FeaturedDNASequence sequence = sequenceController + .retrievePartSequence(userId, partId); + if (sequence == null) { return Response.status(Response.Status.NO_CONTENT).build(); + } return Response.status(Response.Status.OK).entity(sequence).build(); } + /** + * @param partId + * @param sessionId + * @param sequence + * @return the updated sequence + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/sequence") - public FeaturedDNASequence updateSequence(@PathParam("id") long partId, - @QueryParam("sid") String sessionId, - FeaturedDNASequence sequence, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - - String userId = getUserIdFromSessionHeader(userAgentHeader); + public FeaturedDNASequence updateSequence(@PathParam("id") final long partId, + @QueryParam("sid") final String sessionId, final FeaturedDNASequence sequence) { + final String userId = getUserId(sessionId); return sequenceController.updateSequence(userId, partId, sequence); } + /** + * @param partId + * @param sessionId + * @return Response for success or failure + */ @DELETE @Path("/{id}/sequence") - public Response deleteSequence(@PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response deleteSequence(@PathParam("id") final long partId, + @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); try { - if (sequenceController.deleteSequence(userId, partId)) + if (sequenceController.deleteSequence(userId, partId)) { return Response.ok().build(); + } return Response.serverError().build(); - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Logger.error(e); return Response.serverError().build(); } } + /** + * @param info + * @param partData + * @return created part data + */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public PartData create(@Context UriInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - PartData partData) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - EntryCreator creator = new EntryCreator(); - long id = creator.createPart(userId, partData); + public PartData create(@Context final UriInfo info, final PartData partData) { + final String userId = getUserId(); + final EntryCreator creator = new EntryCreator(); + final long id = creator.createPart(userId, partData); log(userId, "created entry " + id); partData.setId(id); return partData; } + /** + * @param partData + * @return created part data + */ @PUT @Path("/transfer") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response transfer(PartData partData) { - EntryCreator creator = new EntryCreator(); - PartData response = creator.receiveTransferredEntry(partData); + public Response transfer(final PartData partData) { + final EntryCreator creator = new EntryCreator(); + final PartData response = creator.receiveTransferredEntry(partData); return super.respond(Response.Status.OK, response); } + /** + * @param info + * @param partId + * @param partData + * @return updated part data + */ @PUT @Path("/{id}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public PartData update(@Context UriInfo info, - @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - PartData partData) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - long id = controller.updatePart(userId, partId, partData); + public PartData update(@Context final UriInfo info, @PathParam("id") final long partId, + final PartData partData) { + final String userId = getUserId(); + final long id = controller.updatePart(userId, partId, partData); log(userId, "updated entry " + id); partData.setId(id); return partData; } + /** + * @param id + */ @DELETE @Path("/{id}") - public void delete(@PathParam("id") long id) { + public void delete(@PathParam("id") final long id) { Logger.info("Deleting part " + id); + // TODO this does nothing but log? } + /** + * @param list + * @return Response for success or failure + */ @POST @Path("/trash") @Consumes(MediaType.APPLICATION_JSON) - public Response moveToTrash(ArrayList list, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - Type fooType = new TypeToken>() { + public Response moveToTrash(final ArrayList list) { + final String userId = getUserId(); + final Type fooType = new TypeToken>() { }.getType(); - Gson gson = new GsonBuilder().create(); - ArrayList data = gson.fromJson(gson.toJsonTree(list), fooType); - boolean success = controller.moveEntriesToTrash(userId, data); + final Gson gson = new GsonBuilder().create(); + final ArrayList data = gson.fromJson(gson.toJsonTree(list), fooType); + final boolean success = controller.moveEntriesToTrash(userId, data); return respond(success); } /** * Removes the linkId from id * - * @param partId id of entry whose link we are removing + * @param partId + * id of entry whose link we are removing * @param linkedPart - * @param sessionId - * @return + * @return Response for success or failure */ @DELETE @Path("/{id}/links/{linkedId}") - public Response deleteLink(@PathParam("id") long partId, - @PathParam("linkedId") long linkedPart, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public Response deleteLink(@PathParam("id") final long partId, + @PathParam("linkedId") final long linkedPart) { + final String userId = getUserId(); log(userId, "removing link " + linkedPart + " from " + partId); - boolean success = controller.removeLink(userId, partId, linkedPart); + final boolean success = controller.removeLink(userId, partId, linkedPart); return respond(success); } } diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index ea43cc3ed..2864efed9 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -97,6 +97,33 @@ protected String getUserId() { return userId; } + /** + * Extract the User ID from a query parameter value or header values in the resource request. + * + * @param sessionId + * a session ID sent via query parameters + * @return a string User ID + * @throws WebApplicationException + * for unauthorized access + */ + protected String getUserId(final String sessionId) { + final Authorization auth; + if (userId != null) { + // we've already looked up the userId + return userId; + } else if ((userId = SessionHandler.getUserIdBySession(sessionId)) != null) { + // try to get user from a session ID, continue to Authorization if fails + } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { + userId = auth.getUserId(); + // TODO validation of meaningful userId + // e.g. "admin" account on EDD won't mean anything to ICE + } + if (userId == null) { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + return userId; + } + /** * @param sessionHeader * not used From 33d5d61e0a97b3dce02fb108670d239c9481a5ae Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 2 Apr 2015 19:04:44 -0700 Subject: [PATCH 05/67] Converted remaining resources --- .../ice/services/rest/PermissionResource.java | 20 +- .../services/rest/RemoteAccessResource.java | 97 ++++--- .../ice/services/rest/SampleResource.java | 161 +++++++----- .../jbei/ice/services/rest/UserResource.java | 246 +++++++++++------- .../jbei/ice/services/rest/WebResource.java | 207 +++++++++------ 5 files changed, 470 insertions(+), 261 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/PermissionResource.java b/src/main/java/org/jbei/ice/services/rest/PermissionResource.java index e2f9f7686..0a4ccb7d3 100644 --- a/src/main/java/org/jbei/ice/services/rest/PermissionResource.java +++ b/src/main/java/org/jbei/ice/services/rest/PermissionResource.java @@ -1,9 +1,9 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; + import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; @@ -21,16 +21,22 @@ public class PermissionResource extends RestResource { private PermissionsController controller = new PermissionsController(); + /** + * @param val + * @param limit + * @return matching groups and users for autocomplete widget + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") - public Response autoComplete(@QueryParam("val") String val, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @DefaultValue("8") @QueryParam("limit") int limit) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - ArrayList result = controller.getMatchingGroupsOrUsers(userId, val, limit); - if (result == null) + public Response autoComplete(@QueryParam("val") final String val, + @DefaultValue("8") @QueryParam("limit") final int limit) { + final String userId = getUserId(); + final ArrayList result = controller.getMatchingGroupsOrUsers(userId, val, + limit); + if (result == null) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR); + } return super.respond(Response.Status.OK, result); } } diff --git a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java index 3358f63c5..624d75f0c 100644 --- a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java @@ -1,9 +1,9 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; + import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -20,9 +20,8 @@ import org.jbei.ice.lib.vo.FeaturedDNASequence; /** - * REST resource for sending/retrieving messages from remote - * ICE instances. Local instances access this resource which contacts the remote - * resource on its behalf + * REST resource for sending/retrieving messages from remote ICE instances. Local instances access + * this resource which contacts the remote resource on its behalf * * @author Hector Plahar */ @@ -32,77 +31,111 @@ public class RemoteAccessResource extends RestResource { private RemoteAccessController controller = new RemoteAccessController(); /** - * @param remoteId unique identifier for remote partner being accessed + * @param remoteId + * unique identifier for remote partner being accessed * @return list of available folders that are available on the registry */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/available") - public ArrayList readRemoteUser(@PathParam("id") long remoteId) { + public ArrayList readRemoteUser(@PathParam("id") final long remoteId) { return controller.getAvailableFolders(remoteId); } + /** + * @param remoteId + * @param email + * @return user from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/users/{email}") - public AccountTransfer getRemoteUser(@PathParam("id") long remoteId, - @PathParam("email") String email) { + public AccountTransfer getRemoteUser(@PathParam("id") final long remoteId, + @PathParam("email") final String email) { return controller.getRemoteUser(remoteId, email); } + /** + * @param remoteId + * @param partId + * @return sequence from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{entryId}/sequence") - public Response getSequence(@PathParam("id") long remoteId, - @PathParam("entryId") long partId) { - FeaturedDNASequence sequence = controller.getRemoteSequence(remoteId, partId); - if (sequence == null) + public Response getSequence(@PathParam("id") final long remoteId, + @PathParam("entryId") final long partId) { + final FeaturedDNASequence sequence = controller.getRemoteSequence(remoteId, partId); + if (sequence == null) { return Response.status(Response.Status.NO_CONTENT).build(); + } return Response.status(Response.Status.OK).entity(sequence).build(); } + /** + * @param remoteId + * @param partId + * @return traces from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{entryId}/traces") - public Response getSequenceTraces(@PathParam("id") long remoteId, - @PathParam("entryId") long partId) { - ArrayList traces = controller.getRemoteTraces(remoteId, partId); - if (traces == null) + public Response getSequenceTraces(@PathParam("id") final long remoteId, + @PathParam("entryId") final long partId) { + final ArrayList traces = controller + .getRemoteTraces(remoteId, partId); + if (traces == null) { return Response.status(Response.Status.NO_CONTENT).build(); + } return Response.status(Response.Status.OK).entity(traces).build(); } + /** + * @param remoteId + * @param folderId + * @param offset + * @param limit + * @param sort + * @param asc + * @return public folders from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/folders/{folderId}") - public FolderDetails getPublicFolderEntries( - @PathParam("id") long remoteId, - @PathParam("folderId") long folderId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public FolderDetails getPublicFolderEntries(@PathParam("id") final long remoteId, + @PathParam("folderId") final long folderId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { return controller.getPublicFolderEntries(remoteId, folderId, sort, asc, offset, limit); } + /** + * @param remoteId + * @param partId + * @return part samples from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{partId}/samples") - public Response getRemotePartSamples(@PathParam("id") long remoteId, - @PathParam("partId") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - ArrayList result = controller.getRemotePartSamples(remoteId, partId); + public Response getRemotePartSamples(@PathParam("id") final long remoteId, + @PathParam("partId") final long partId) { + final ArrayList result = controller.getRemotePartSamples(remoteId, partId); return super.respond(result); } + /** + * @param remoteId + * @param partId + * @return comments from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{partId}/comments") - public Response getRemotePartComments(@PathParam("id") long remoteId, - @PathParam("partId") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - ArrayList result = controller.getRemotePartComments(remoteId, partId); + public Response getRemotePartComments(@PathParam("id") final long remoteId, + @PathParam("partId") final long partId) { + final ArrayList result = controller.getRemotePartComments(remoteId, partId); return super.respond(result); } } diff --git a/src/main/java/org/jbei/ice/services/rest/SampleResource.java b/src/main/java/org/jbei/ice/services/rest/SampleResource.java index 2ef01c76d..ecf416c61 100644 --- a/src/main/java/org/jbei/ice/services/rest/SampleResource.java +++ b/src/main/java/org/jbei/ice/services/rest/SampleResource.java @@ -1,5 +1,20 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.StorageLocation; import org.jbei.ice.lib.dto.sample.PartSample; @@ -9,12 +24,6 @@ import org.jbei.ice.lib.entry.sample.RequestRetriever; import org.jbei.ice.lib.entry.sample.SampleController; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.List; - /** * REST Resource for samples * @@ -26,120 +35,154 @@ public class SampleResource extends RestResource { private RequestRetriever requestRetriever = new RequestRetriever(); private SampleController sampleController = new SampleController(); + /** + * @param token + * @return Response with matching part sample + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("{token}") - public Response getSampleByToken(@PathParam("token") String token) { + public Response getSampleByToken(@PathParam("token") final String token) { try { - ArrayList result = sampleController.getSamplesByBarcode(null, token); + final ArrayList result = sampleController.getSamplesByBarcode(null, token); return super.respond(result); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return super.respond(false); } } + /** + * @param offset + * @param limit + * @param sort + * @param asc + * @param filter + * @param status + * @return Response with matching samples + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/requests") - public Response getRequests( - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("requested") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @QueryParam("filter") String filter, - @QueryParam("status") SampleRequestStatus status, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response getRequests(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("requested") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc, + @QueryParam("filter") final String filter, + @QueryParam("status") final SampleRequestStatus status) { + final String userId = getUserId(); Logger.info(userId + ": retrieving sample requests"); - UserSamples samples = requestRetriever.getRequests(userId, offset, limit, sort, asc, status, filter); + final UserSamples samples = requestRetriever.getRequests(userId, offset, limit, sort, asc, + status, filter); return super.respond(Response.Status.OK, samples); } /** - * Sets the status of sample requests. Must have admin privs to set the sample for others - * This is intended for requesting samples + * Sets the status of sample requests. Must have admin privs to set the sample for others This + * is intended for requesting samples * - * @param sessionId session identifier + * @param status + * @param requestIds + * @return Response success or failure */ @PUT @Path("/requests") - public Response setRequestStatus( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @QueryParam("status") SampleRequestStatus status, - ArrayList requestIds) { - String userId = getUserIdFromSessionHeader(sessionId); + public Response setRequestStatus(@QueryParam("status") final SampleRequestStatus status, + final ArrayList requestIds) { + final String userId = getUserId(); try { - if (requestIds == null || requestIds.isEmpty()) + if (requestIds == null || requestIds.isEmpty()) { return super.respond(Response.Status.OK); + } - ArrayList sampleRequestIds = new ArrayList<>(); - for (Number number : requestIds) + final ArrayList sampleRequestIds = new ArrayList<>(); + for (final Number number : requestIds) { sampleRequestIds.add(number.longValue()); + } - boolean success = requestRetriever.setRequestsStatus(userId, sampleRequestIds, status); + final boolean success = requestRetriever.setRequestsStatus(userId, sampleRequestIds, + status); return super.respond(success); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return super.respond(Response.Status.INTERNAL_SERVER_ERROR); } } + /** + * @param requestId + * @return Response with the removed sample + */ @DELETE @Path("/requests/{id}") - public Response deleteSampleRequest(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @PathParam("id") long requestId) { - String userId = getUserIdFromSessionHeader(sessionId); + public Response deleteSampleRequest(@PathParam("id") final long requestId) { + final String userId = getUserId(); return respond(Response.Status.OK, requestRetriever.removeSampleFromCart(userId, requestId)); } + /** + * @param requestId + * @param status + * @return Response with the updated sample request + */ @PUT @Path("/requests/{id}") - public Response updateSampleRequest( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @PathParam("id") long requestId, - @QueryParam("status") SampleRequestStatus status) { - String userId = getUserIdFromSessionHeader(sessionId); - SampleRequest request = requestRetriever.updateStatus(userId, requestId, status); + public Response updateSampleRequest(@PathParam("id") final long requestId, + @QueryParam("status") final SampleRequestStatus status) { + final String userId = getUserId(); + final SampleRequest request = requestRetriever.updateStatus(userId, requestId, status); return respond(Response.Status.OK, request); } + /** + * @param offset + * @param limit + * @param sort + * @param asc + * @param uid + * @param status + * @return response with the matching sample requests + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/requests/{userId}") - public Response getUserRequests( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("requested") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @PathParam("userId") long uid, - @DefaultValue("IN_CART") @QueryParam("status") SampleRequestStatus status) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response getUserRequests(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("requested") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc, + @PathParam("userId") final long uid, + @DefaultValue("IN_CART") @QueryParam("status") final SampleRequestStatus status) { + final String userId = getUserId(); Logger.info(userId + ": retrieving sample requests for user"); - UserSamples userSamples = requestRetriever.getUserSamples(userId, status, offset, limit, sort, asc); + final UserSamples userSamples = requestRetriever.getUserSamples(userId, status, offset, + limit, sort, asc); return super.respond(Response.Status.OK, userSamples); } + /** + * @param request + * @return Response with the added sample requests + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/requests") - public ArrayList addRequest( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - SampleRequest request) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList addRequest(final SampleRequest request) { + final String userId = getUserId(); log(userId, "add sample request to cart for " + request.getPartData().getId()); return requestRetriever.placeSampleInCart(userId, request); } + /** + * @param type + * @return Response with the current sample requests + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/storage/{type}") public Response getSampleStorageType( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @DefaultValue("IN_CART") @QueryParam("type") String type) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - List locations = sampleController.getStorageLocations(userId, type); + @DefaultValue("IN_CART") @QueryParam("type") final String type) { + final String userId = getUserId(); + final List locations = sampleController.getStorageLocations(userId, type); return respond(locations); } } diff --git a/src/main/java/org/jbei/ice/services/rest/UserResource.java b/src/main/java/org/jbei/ice/services/rest/UserResource.java index 4653cb2b5..5ad91f815 100644 --- a/src/main/java/org/jbei/ice/services/rest/UserResource.java +++ b/src/main/java/org/jbei/ice/services/rest/UserResource.java @@ -1,5 +1,22 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.jbei.ice.lib.account.AccountController; import org.jbei.ice.lib.account.AccountTransfer; import org.jbei.ice.lib.account.PreferencesController; @@ -17,14 +34,6 @@ import org.jbei.ice.lib.group.GroupController; import org.jbei.ice.lib.shared.ColumnField; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; -import java.util.List; - /** * REST Resource for users * @@ -38,21 +47,22 @@ public class UserResource extends RestResource { private RequestRetriever requestRetriever = new RequestRetriever(); /** - * Retrieves list of users that are available to user making request. Availability is - * defined by being in the same group if the user does not have admin privileges. + * Retrieves list of users that are available to user making request. Availability is defined by + * being in the same group if the user does not have admin privileges. * - * @param sessionId unique user session identifier + * @param offset + * @param limit + * @param sort + * @param asc * @return wrapper around list of users */ @GET @Produces(MediaType.APPLICATION_JSON) - public AccountResults get( - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("lastName") @QueryParam("sort") String sort, - @DefaultValue("true") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public AccountResults get(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("lastName") @QueryParam("sort") final String sort, + @DefaultValue("true") @QueryParam("asc") final boolean asc) { + final String userId = getUserId(); log(userId, "retrieving available accounts"); return groupController.getAvailableAccounts(userId, offset, limit, asc, sort); } @@ -60,159 +70,215 @@ public AccountResults get( /** * Retrieves (up to specified limit), the list of users that match the value * - * @param val text to match against users - * @param limit upper limit for number of users to return - * @param sessionId unique user session identifier + * @param val + * text to match against users + * @param limit + * upper limit for number of users to return * @return list of matching users */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") public ArrayList getAutoCompleteForAvailableAccounts( - @QueryParam("val") String val, - @DefaultValue("8") @QueryParam("limit") int limit, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + @QueryParam("val") final String val, + @DefaultValue("8") @QueryParam("limit") final int limit) { + final String userId = getUserId(); return controller.getMatchingAccounts(userId, val, limit); } + /** + * @param info + * @param userId + * @return account information for transfer + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public AccountTransfer read(@Context UriInfo info, @PathParam("id") String userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public AccountTransfer read(@Context final UriInfo info, @PathParam("id") final String userId) { Account account; - if (userId.matches("\\d+(\\.\\d+)?")) + if (userId.matches("\\d+(\\.\\d+)?")) { account = controller.get(Long.decode(userId)); - else + } else { account = controller.getByEmail(userId); + } - if (account != null) + if (account != null) { return account.toDataTransferObject(); + } return null; } + /** + * @param info + * @param userId + * @return group listing for a user + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/groups") - public ArrayList getProfileGroups(@Context UriInfo info, @PathParam("id") long userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList getProfileGroups(@Context final UriInfo info, + @PathParam("id") final long userId) { + final String userIdString = getUserId(); return groupController.retrieveUserGroups(userIdString, userId, false); } + /** + * @param userId + * @param userGroup + * @return created group + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/groups") - public UserGroup createGroup(@PathParam("id") long userId, - UserGroup userGroup, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); + public UserGroup createGroup(@PathParam("id") final long userId, final UserGroup userGroup) { + final String userIdString = getUserId(); return groupController.createGroup(userIdString, userGroup); } + /** + * @param info + * @param userId + * @param offset + * @param limit + * @param sort + * @param asc + * @return collection for user's part entries + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") - public FolderDetails getProfileEntries(@Context UriInfo info, - @PathParam("id") long userId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); - EntryController entryController = new EntryController(); - ColumnField field = ColumnField.valueOf(sort.toUpperCase()); - - Account requestAccount = DAOFactory.getAccountDAO().get(userId); - List entries = entryController.retrieveOwnerEntries(userIdString, requestAccount.getEmail(), field, - asc, offset, limit); - long count = entryController.getNumberOfOwnerEntries(userIdString, requestAccount.getEmail()); - FolderDetails details = new FolderDetails(); + public FolderDetails getProfileEntries(@Context final UriInfo info, + @PathParam("id") final long userId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { + final String userIdString = getUserId(); + final EntryController entryController = new EntryController(); + final ColumnField field = ColumnField.valueOf(sort.toUpperCase()); + + final Account requestAccount = DAOFactory.getAccountDAO().get(userId); + final List entries = entryController.retrieveOwnerEntries(userIdString, + requestAccount.getEmail(), field, asc, offset, limit); + final long count = entryController.getNumberOfOwnerEntries(userIdString, + requestAccount.getEmail()); + final FolderDetails details = new FolderDetails(); details.getEntries().addAll(entries); details.setCount(count); return details; } + /** + * @param info + * @param userId + * @return preferences for a user + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/preferences") - public UserPreferences getUserPreferences(@Context UriInfo info, - @PathParam("id") long userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); - PreferencesController preferencesController = new PreferencesController(); + public UserPreferences getUserPreferences(@Context final UriInfo info, + @PathParam("id") final long userId) { + final String userIdString = getUserId(); + final PreferencesController preferencesController = new PreferencesController(); return preferencesController.getUserPreferences(userIdString, userId); } + /** + * @param userId + * @param key + * @param value + * @return updated preferences for a user + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/preferences/{key}") - public PreferenceInfo updatePreference( - @PathParam("id") long userId, - @PathParam("key") String key, - @QueryParam("value") String value, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); - PreferencesController preferencesController = new PreferencesController(); + public PreferenceInfo updatePreference(@PathParam("id") final long userId, + @PathParam("key") final String key, @QueryParam("value") final String value) { + final String userIdString = getUserId(); + final PreferencesController preferencesController = new PreferencesController(); return preferencesController.updatePreference(userIdString, userId, key, value); } + /** + * @param info + * @param userId + * @param transfer + * @return updated user information + */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public AccountTransfer update(@Context UriInfo info, @PathParam("id") long userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - AccountTransfer transfer) { - String user = getUserIdFromSessionHeader(userAgentHeader); + public AccountTransfer update(@Context final UriInfo info, @PathParam("id") final long userId, + final AccountTransfer transfer) { + final String user = getUserId(); return controller.updateAccount(user, userId, transfer); } + /** + * @param info + * @param transfer + * @return Response for success or failure + */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/password") - public Response resetPassword(@Context UriInfo info, AccountTransfer transfer) { - boolean success = controller.resetPassword(transfer.getEmail()); - if (!success) + public Response resetPassword(@Context final UriInfo info, final AccountTransfer transfer) { + final boolean success = controller.resetPassword(transfer.getEmail()); + if (!success) { return super.respond(Response.Status.NOT_FOUND); + } return super.respond(Response.Status.OK); } + /** + * @param transfer + * @return updated user information + */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/password") - public AccountTransfer updatePassword( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - AccountTransfer transfer) { - String user = getUserIdFromSessionHeader(sessionId); + public AccountTransfer updatePassword(final AccountTransfer transfer) { + final String user = getUserId(); return controller.updatePassword(user, transfer); } + /** + * @param accountTransfer + * @return Response with created user information + */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response createNewUser(AccountTransfer accountTransfer) { - accountTransfer = controller.createNewAccount(accountTransfer, true); - return super.respond(accountTransfer); + public Response createNewUser(final AccountTransfer accountTransfer) { + final AccountTransfer created = controller.createNewAccount(accountTransfer, true); + return super.respond(created); } + /** + * @param userId + * @param offset + * @param limit + * @param sort + * @param asc + * @param uid + * @param status + * @return Response with user's samples + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples") - public Response getRequestedSamples(@PathParam("id") long userId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("requested") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @PathParam("userId") long uid, - @DefaultValue("") @QueryParam("status") SampleRequestStatus status, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String user = getUserIdFromSessionHeader(userAgentHeader); - return super.respond(Response.Status.OK, requestRetriever.getUserSamples(user, status, offset, limit, sort, - asc)); + public Response getRequestedSamples(@PathParam("id") final long userId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("requested") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc, + @PathParam("userId") final long uid, + @DefaultValue("") @QueryParam("status") final SampleRequestStatus status) { + final String user = getUserId(); + return super.respond(Response.Status.OK, + requestRetriever.getUserSamples(user, status, offset, limit, sort, asc)); } } diff --git a/src/main/java/org/jbei/ice/services/rest/WebResource.java b/src/main/java/org/jbei/ice/services/rest/WebResource.java index 17b680980..32737a6be 100644 --- a/src/main/java/org/jbei/ice/services/rest/WebResource.java +++ b/src/main/java/org/jbei/ice/services/rest/WebResource.java @@ -1,5 +1,21 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.jbei.ice.lib.dto.entry.AttachmentInfo; import org.jbei.ice.lib.dto.entry.PartData; import org.jbei.ice.lib.dto.entry.PartStatistics; @@ -11,13 +27,6 @@ import org.jbei.ice.lib.net.WoRController; import org.jbei.ice.lib.vo.FeaturedDNASequence; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; - /** * @author Hector Plahar */ @@ -28,149 +37,201 @@ public class WebResource extends RestResource { private RemoteAccessController remoteAccessController = new RemoteAccessController(); /** - * Retrieves information on other ice instances that is in a web of registries - * configuration with this instance; also know as registry partners + * Retrieves information on other ice instances that is in a web of registries configuration + * with this instance; also know as registry partners * - * @param approvedOnly if true, only instances that have been approved are returned; defaults to true - * @param userAgentHeader session if for user + * @param approvedOnly + * if true, only instances that have been approved are returned; defaults to true * @return wrapper around the list of registry partners */ @GET @Produces(MediaType.APPLICATION_JSON) public WebOfRegistries query( - @DefaultValue("true") @QueryParam("approved_only") boolean approvedOnly, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + @DefaultValue("true") @QueryParam("approved_only") final boolean approvedOnly) { + getUserId(); // ensure valid session or auth header return controller.getRegistryPartners(approvedOnly); } - // get public entries + /** + * get public entries + * + * @param uriInfo + * @param partnerId + * @param offset + * @param limit + * @param sort + * @param asc + * @return Response with public entries from registry partners + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") - public Response getWebEntries(@Context UriInfo uriInfo, - @PathParam("id") long partnerId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - WebEntries result = remoteAccessController.getPublicEntries(partnerId, offset, limit, sort, asc); + public Response getWebEntries(@Context final UriInfo uriInfo, + @PathParam("id") final long partnerId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { + final WebEntries result = remoteAccessController.getPublicEntries(partnerId, offset, limit, + sort, asc); return super.respond(Response.Status.OK, result); } + /** + * @param partnerId + * @param partId + * @return attachment info on a registry partner entry + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/attachments") - public ArrayList getAttachments(@PathParam("id") long partnerId, - @PathParam("entryId") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { -// String userId = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList getAttachments(@PathParam("id") final long partnerId, + @PathParam("entryId") final long partId) { return remoteAccessController.getPublicEntryAttachments(partnerId, partId); } + /** + * @param remoteId + * @param entrySelection + * @return Response for success + */ @POST @Path("/{id}/transfer") - public Response transferEntries( - @PathParam("id") long remoteId, - EntrySelection entrySelection, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = super.getUserIdFromSessionHeader(sessionId); + public Response transferEntries(@PathParam("id") final long remoteId, + final EntrySelection entrySelection) { + final String userId = super.getUserId(); remoteAccessController.transferEntries(userId, remoteId, entrySelection); return super.respond(Response.Status.OK); } + /** + * @param uriInfo + * @param partnerId + * @param entryId + * @return Response with a specific entry for a registry partner + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}") - public Response getWebEntry(@Context UriInfo uriInfo, - @PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - PartData result = remoteAccessController.getPublicEntry(partnerId, entryId); + public Response getWebEntry(@Context final UriInfo uriInfo, + @PathParam("id") final long partnerId, @PathParam("entryId") final long entryId) { + final PartData result = remoteAccessController.getPublicEntry(partnerId, entryId); return super.respond(Response.Status.OK, result); } + /** + * @param uriInfo + * @param partnerId + * @param entryId + * @return Response with a specific entry tooltip for a registry partner + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/tooltip") - public Response getWebEntryTooltip(@Context UriInfo uriInfo, - @PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - PartData result = remoteAccessController.getPublicEntryTooltip(partnerId, entryId); + public Response getWebEntryTooltip(@Context final UriInfo uriInfo, + @PathParam("id") final long partnerId, @PathParam("entryId") final long entryId) { + final PartData result = remoteAccessController.getPublicEntryTooltip(partnerId, entryId); return super.respond(Response.Status.OK, result); } + /** + * @param partnerId + * @param entryId + * @return Response with statistics on a specific entry for a registry partner + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/statistics") - public Response getStatistics(@PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - PartStatistics statistics = remoteAccessController.getPublicEntryStatistics(partnerId, entryId); + public Response getStatistics(@PathParam("id") final long partnerId, + @PathParam("entryId") final long entryId) { + final PartStatistics statistics = remoteAccessController.getPublicEntryStatistics( + partnerId, entryId); return super.respond(statistics); } + /** + * @param uriInfo + * @param partnerId + * @param entryId + * @return Response with a sequence on a registry partner entry + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/sequence") - public Response getWebEntrySequence(@Context UriInfo uriInfo, - @PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - FeaturedDNASequence result = remoteAccessController.getPublicEntrySequence(partnerId, entryId); + public Response getWebEntrySequence(@Context final UriInfo uriInfo, + @PathParam("id") final long partnerId, @PathParam("entryId") final long entryId) { + final FeaturedDNASequence result = remoteAccessController.getPublicEntrySequence(partnerId, + entryId); return super.respond(Response.Status.OK, result); } + /** + * @param info + * @param partner + * @return Response with an added registry partner + */ @POST @Path("/partner") // admin function - public Response addWebPartner(@Context UriInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - RegistryPartner partner) { - String userId = getUserIdFromSessionHeader(sessionId); - RegistryPartner registryPartner = controller.addWebPartner(userId, partner); + public Response addWebPartner(@Context final UriInfo info, final RegistryPartner partner) { + final String userId = getUserId(); + final RegistryPartner registryPartner = controller.addWebPartner(userId, partner); return respond(Response.Status.OK, registryPartner); } + /** + * @param info + * @param partnerId + * @return Response with registry partner info + */ @GET @Path("/partner/{id}") - public Response getWebPartner(@Context UriInfo info, - @PathParam("id") long partnerId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - RegistryPartner partner = controller.getWebPartner(userId, partnerId); + public Response getWebPartner(@Context final UriInfo info, @PathParam("id") final long partnerId) { + final String userId = getUserId(); + final RegistryPartner partner = controller.getWebPartner(userId, partnerId); return super.respond(Response.Status.OK, partner); } + /** + * @param partner + * @return Response for success or failure + */ @POST @Path("/partner/remote") - public Response remoteWebPartnerRequest(RegistryPartner partner) { - if (controller.addRemoteWebPartner(partner)) + public Response remoteWebPartnerRequest(final RegistryPartner partner) { + if (controller.addRemoteWebPartner(partner)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param url + * @param partner + * @return Response for success or failure + */ @PUT @Path("/partner/{url}") - public Response updateWebPartner( - @PathParam("url") String url, RegistryPartner partner, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.updateWebPartner(userId, url, partner)) + public Response updateWebPartner(@PathParam("url") final String url, + final RegistryPartner partner) { + final String userId = getUserId(); + if (controller.updateWebPartner(userId, url, partner)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param url + * @return Response for success or failure + */ @DELETE @Path("/partner/{url}") - public Response removeWebPartner( - @PathParam("url") String url, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.removeWebPartner(userId, url)) + public Response removeWebPartner(@PathParam("url") final String url) { + final String userId = getUserId(); + if (controller.removeWebPartner(userId, url)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } } From 37e571694b2e17b8ebfcee49c202ca0947eb716a Mon Sep 17 00:00:00 2001 From: William Morrell Date: Tue, 7 Apr 2015 14:24:34 -0700 Subject: [PATCH 06/67] Need to explicitly begin/end transaction during initialization of KeyTable for looking up HMAC auth keys --- .../java/org/jbei/ice/services/rest/RestResource.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index 2864efed9..bc433a5f4 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -18,6 +18,7 @@ import org.jbei.auth.hmac.HmacSignatureFactory; import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; +import org.jbei.ice.lib.dao.hibernate.HibernateUtil; import org.jbei.ice.lib.dto.ConfigurationKey; import org.jbei.ice.lib.utils.Utils; @@ -32,8 +33,14 @@ public class RestResource { private static final KeyTable TABLE = new KeyTable() { // keys stored in /var/lib/tomcat6/data/rest-auth by default - private final File directory = Paths.get( - Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), "rest-auth").toFile(); + private final File directory; + { + // need to force-create a transaction to get the DATA_DIRECTORY config value + HibernateUtil.beginTransaction(); + directory = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + "rest-auth").toFile(); + HibernateUtil.commitTransaction(); + } @Override public Key getKey(final String keyId) { From f524cd994ca6644e29824780d7b78bbadd3f40ba Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 8 Apr 2015 18:09:14 -0700 Subject: [PATCH 07/67] Including jbei-repo for including rest-util artifact --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 407f145fe..5d7ca63c6 100755 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,11 @@ Sonatype OSS Snapshot Repository https://oss.sonatype.org/content/repositories/snapshots/ + + jbei-repo + JBEI Maven Repository + https://repo.jbei.org/artifactory/repo/ + From 032f77a40eb10db1e9f1336c979286f73d4bd836 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 9 Apr 2015 13:42:12 -0700 Subject: [PATCH 08/67] Changing the repository ID to match existing settings --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5d7ca63c6..08daec25b 100755 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ https://oss.sonatype.org/content/repositories/snapshots/ - jbei-repo + repo.jbei.org JBEI Maven Repository https://repo.jbei.org/artifactory/repo/ From 405bbfc6f7fdbb5898777db0652a14c798ff46db Mon Sep 17 00:00:00 2001 From: William Morrell Date: Fri, 10 Apr 2015 14:53:07 -0700 Subject: [PATCH 09/67] Switch out hard-coded Local auth for Ldap auth --- src/main/java/org/jbei/ice/lib/account/AccountController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/account/AccountController.java b/src/main/java/org/jbei/ice/lib/account/AccountController.java index fcfb6fd39..a15c044d4 100755 --- a/src/main/java/org/jbei/ice/lib/account/AccountController.java +++ b/src/main/java/org/jbei/ice/lib/account/AccountController.java @@ -5,7 +5,7 @@ import org.jbei.ice.lib.account.authentication.AuthenticationException; import org.jbei.ice.lib.account.authentication.IAuthentication; import org.jbei.ice.lib.account.authentication.InvalidCredentialsException; -import org.jbei.ice.lib.account.authentication.LocalAuthentication; +import org.jbei.ice.lib.account.authentication.LblLdapAuthentication; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.account.model.AccountPreferences; import org.jbei.ice.lib.common.logging.Logger; @@ -333,7 +333,7 @@ public boolean isAdministrator(String userId) { * @throws InvalidCredentialsException */ public String authenticate(String login, String password, String ip) throws InvalidCredentialsException { - IAuthentication authentication = new LocalAuthentication(); + IAuthentication authentication = new LblLdapAuthentication(); String email; try { From 8080f5134babcd92754828cf4ab35816777c8b3e Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 15 Apr 2015 19:24:59 -0700 Subject: [PATCH 10/67] Adding truststore configuration to Jetty. --- jetty-debug.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jetty-debug.xml b/jetty-debug.xml index 3c3645caa..4f1008997 100644 --- a/jetty-debug.xml +++ b/jetty-debug.xml @@ -34,10 +34,11 @@ 8443 30000 - /.keystore - + /.keystore changeit changeit + /.keystore + changeit From 330559d0181d96bab5b13a09a2cb4bd6f4c63801 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 15 Apr 2015 19:44:03 -0700 Subject: [PATCH 11/67] Updating pom with minimum maven version, and updated minor versions of dependencies and plugins found with `mvn versions:display-dependency-updates versions:display-plugin-updates` --- pom.xml | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 08daec25b..27af87779 100755 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,9 @@ 4.1.13 ice Inventory of Composable Elements (ICE) for Synthetic Biology + + 2.2.1 + biojava-maven-repo @@ -27,12 +30,12 @@ org.glassfish.jersey.containers jersey-container-servlet-core - 2.13 + 2.17 org.glassfish.jersey.media jersey-media-multipart - 2.13 + 2.17 javax.servlet @@ -43,7 +46,7 @@ postgresql postgresql - 9.1-901.jdbc4 + 9.3-1100.jdbc41 org.hsqldb @@ -53,13 +56,13 @@ junit junit - 4.11 + 4.12 test com.google.code.gson gson - 2.2.4 + 2.3.1 compile @@ -110,7 +113,7 @@ org.apache.commons commons-email - 1.3.1 + 1.3.3 net.sf.opencsv @@ -120,17 +123,17 @@ org.apache.httpcomponents httpcore - 4.2.2 + 4.4.1 org.apache.httpcomponents httpclient - 4.2.1 + 4.4.1 ch.qos.logback logback-classic - 1.0.13 + 1.1.3 org.biojava @@ -183,7 +186,7 @@ true org.apache.maven.plugins maven-compiler-plugin - 2.3.2 + 3.3 1.7 1.7 @@ -203,7 +206,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 2.10.3 From e3d679d641f1d1e229a3bcfa7fe428051d38ae57 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 15 Apr 2015 20:31:27 -0700 Subject: [PATCH 12/67] Moved HMAC authentication to a request filter/interceptor to get access to request message body before conversion to POJO entity --- .../rest/AuthenticationInterceptor.java | 125 ++++++++++++++++++ .../jbei/ice/services/rest/RestResource.java | 85 ++---------- .../rest/multipart/IceApplication.java | 7 +- src/main/resources/logback.xml | 3 + 4 files changed, 146 insertions(+), 74 deletions(-) create mode 100644 src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java diff --git a/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java new file mode 100644 index 000000000..32b2415ed --- /dev/null +++ b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java @@ -0,0 +1,125 @@ +/** + * + */ +package org.jbei.ice.services.rest; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Paths; +import java.security.Key; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.jbei.auth.KeyTable; +import org.jbei.auth.hmac.HmacAuthorizor; +import org.jbei.auth.hmac.HmacSignature; +import org.jbei.auth.hmac.HmacSignatureFactory; +import org.jbei.ice.lib.dao.hibernate.HibernateUtil; +import org.jbei.ice.lib.dto.ConfigurationKey; +import org.jbei.ice.lib.utils.Utils; + +/** + * Filter watches for Authorization headers on incoming requests, and passes along data to build an + * {@link HmacSignature} to validate the request. + * + * @author wcmorrell + * @version 4.2 + * @since 4.2 + */ +@Priority(Priorities.AUTHENTICATION) +public class AuthenticationInterceptor implements ContainerRequestFilter, ReaderInterceptor { + + /** + * Property/Attribute name for mapping the expected value of the generated signature. + */ + public static final String EXPECTED_SIGNATURE = "org.jbei.auth.signature"; + + /** + * Property/Attribute name for mapping the {@link HmacSignature} object for the request. + */ + public static final String HMAC_SIGNATURE = "org.jbei.auth.hmac"; + + private static final Logger log = LoggerFactory.getLogger(HmacAuthorizor.class); + + // do lookup by using existing configuration DATA_DIRECTORY to find key names => key data + private static final KeyTable TABLE = new KeyTable() { + + // keys stored in /var/lib/tomcat6/data/rest-auth by default + private final File directory; + { + // need to force-create a transaction to get the DATA_DIRECTORY config value + HibernateUtil.beginTransaction(); + directory = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + "rest-auth").toFile(); + HibernateUtil.commitTransaction(); + } + + @Override + public Key getKey(final String keyId) { + try { + // find file named by keyId in the directory + final File keyFile = new File(directory, keyId); + // collect all lines in the file to a buffer + final StringBuilder encoded = new StringBuilder(); + try (final FileReader reader = new FileReader(keyFile); + final BufferedReader buffered = new BufferedReader(reader);) { + String line; + while ((line = buffered.readLine()) != null) { + encoded.append(line); + } + // after reading all lines, decode value into a Key object + return HmacSignatureFactory.decodeKey(encoded.toString()); + } + } catch (final Throwable t) { + log.error("Failed to load rest-auth key " + keyId); + } + return null; + } + + }; + + private static final HmacAuthorizor AUTHORIZOR = new HmacAuthorizor(TABLE); + + @Override + public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, + WebApplicationException { + final Object hmac = context.getProperty(HMAC_SIGNATURE); + if (hmac != null && hmac instanceof HmacSignature) { + context.setInputStream(((HmacSignature) hmac).filterInput(context.getInputStream())); + } + return context.proceed(); + } + + @Override + public void filter(final ContainerRequestContext requestContext) throws IOException { + final String hmac = requestContext.getHeaderString("Authorization"); + final String[] parts = StringUtils.split(hmac, ':'); + if (parts == null || parts.length == 0) { + log.debug("No Authorization header found on request"); + } else if (!"1".equals(parts[0]) || parts.length != 4) { + log.debug("Unknown Authorization header format"); + } else { + final UriInfo uriInfo = requestContext.getUriInfo(); + final MultivaluedMap params = uriInfo.getQueryParameters(false); + final HmacSignature sig = AUTHORIZOR.initSignature(hmac, requestContext.getMethod(), + requestContext.getHeaderString("Host"), uriInfo.getPath(), params); + requestContext.setProperty(HMAC_SIGNATURE, sig); + requestContext.setProperty(EXPECTED_SIGNATURE, parts[3]); + } + } + +} diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index bc433a5f4..b5603d87e 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -1,26 +1,14 @@ package org.jbei.ice.services.rest; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.nio.file.Paths; -import java.security.Key; - import javax.servlet.http.HttpServletRequest; import javax.ws.rs.HeaderParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; -import org.jbei.auth.Authorization; -import org.jbei.auth.KeyTable; -import org.jbei.auth.hmac.HmacAuthorizor; -import org.jbei.auth.hmac.HmacSignatureFactory; +import org.jbei.auth.hmac.HmacSignature; import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; -import org.jbei.ice.lib.dao.hibernate.HibernateUtil; -import org.jbei.ice.lib.dto.ConfigurationKey; -import org.jbei.ice.lib.utils.Utils; /** * Parent class for all rest resource objects @@ -29,45 +17,6 @@ */ public class RestResource { - // do lookup by using existing configuration DATA_DIRECTORY to find key names => key data - private static final KeyTable TABLE = new KeyTable() { - - // keys stored in /var/lib/tomcat6/data/rest-auth by default - private final File directory; - { - // need to force-create a transaction to get the DATA_DIRECTORY config value - HibernateUtil.beginTransaction(); - directory = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), - "rest-auth").toFile(); - HibernateUtil.commitTransaction(); - } - - @Override - public Key getKey(final String keyId) { - try { - // find file named by keyId in the directory - final File keyFile = new File(directory, keyId); - // collect all lines in the file to a buffer - final StringBuilder encoded = new StringBuilder(); - try (final FileReader reader = new FileReader(keyFile); - final BufferedReader buffered = new BufferedReader(reader);) { - String line; - while ((line = buffered.readLine()) != null) { - encoded.append(line); - } - // after reading all lines, decode value into a Key object - return HmacSignatureFactory.decodeKey(encoded.toString()); - } - } catch (final Throwable t) { - Logger.error("Failed to load rest-auth key " + keyId); - } - return null; - } - - }; - - private static final HmacAuthorizor AUTHORIZOR = new HmacAuthorizor(TABLE); - @HeaderParam(value = "X-ICE-Authentication-SessionId") private String sessionId; @@ -87,21 +36,7 @@ public Key getKey(final String keyId) { * for unauthorized access */ protected String getUserId() { - final Authorization auth; - if (userId != null) { - // we've already looked up the userId - return userId; - } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { - userId = auth.getUserId(); - // TODO validation of meaningful userId - // e.g. "admin" account on EDD won't mean anything to ICE - } else if (sessionId != null) { - userId = SessionHandler.getUserIdBySession(sessionId); - } - if (userId == null) { - throw new WebApplicationException(Response.Status.UNAUTHORIZED); - } - return userId; + return getUserId(sessionId); } /** @@ -114,16 +49,22 @@ protected String getUserId() { * for unauthorized access */ protected String getUserId(final String sessionId) { - final Authorization auth; if (userId != null) { // we've already looked up the userId return userId; } else if ((userId = SessionHandler.getUserIdBySession(sessionId)) != null) { // try to get user from a session ID, continue to Authorization if fails - } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { - userId = auth.getUserId(); - // TODO validation of meaningful userId - // e.g. "admin" account on EDD won't mean anything to ICE + } else { + final Object hmac = request.getAttribute(AuthenticationInterceptor.HMAC_SIGNATURE); + final Object valid = request.getAttribute(AuthenticationInterceptor.EXPECTED_SIGNATURE); + if (hmac != null && hmac instanceof HmacSignature) { + final HmacSignature generated = (HmacSignature) hmac; + if (generated.generateSignature().equals(valid)) { + // TODO validation of meaningful userId + // e.g. "admin" account on EDD won't mean anything to ICE + userId = generated.getUserId(); + } + } } if (userId == null) { throw new WebApplicationException(Response.Status.UNAUTHORIZED); diff --git a/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java b/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java index 2a88b1447..a57d5cd9c 100644 --- a/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java +++ b/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java @@ -2,12 +2,14 @@ import java.util.HashSet; import java.util.Set; -import javax.ws.rs.core.Application; -import org.jbei.ice.services.rest.FileResource; +import javax.ws.rs.core.Application; import org.glassfish.jersey.media.multipart.MultiPartFeature; +import org.jbei.ice.services.rest.AuthenticationInterceptor; +import org.jbei.ice.services.rest.FileResource; + /** * @author Hector Plahar */ @@ -19,6 +21,7 @@ public Set> getClasses() { // register resources and features classes.add(MultiPartFeature.class); classes.add(FileResource.class); + classes.add(AuthenticationInterceptor.class); return classes; } } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 4fbae12fa..c1ee71509 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -17,6 +17,9 @@ + + + From 7126b0e311dc285724980fe8b62ceb9f0e91996f Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 16 Apr 2015 17:31:02 -0700 Subject: [PATCH 13/67] Modifying logback config again to prevent duplicate logs on the org.jbei.auth logger + root logger --- src/main/resources/logback.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index c1ee71509..b120a8a08 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -17,7 +17,7 @@ - + From ec52ab0eabc7f7313d4309c573f4a91f0c531ec7 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 16 Apr 2015 17:31:56 -0700 Subject: [PATCH 14/67] Change AccountControler to load authentication backend class from database setting, default fallback is LocalAuthentication --- .../ice/lib/account/AccountController.java | 444 +++++++++++------- .../jbei/ice/lib/dto/ConfigurationKey.java | 4 +- .../jbei/ice/services/rest/UserResource.java | 2 +- 3 files changed, 285 insertions(+), 165 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/account/AccountController.java b/src/main/java/org/jbei/ice/lib/account/AccountController.java index a15c044d4..4f5420345 100755 --- a/src/main/java/org/jbei/ice/lib/account/AccountController.java +++ b/src/main/java/org/jbei/ice/lib/account/AccountController.java @@ -1,11 +1,19 @@ package org.jbei.ice.lib.account; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Set; + import org.apache.commons.lang.StringUtils; +import org.slf4j.LoggerFactory; + import org.jbei.ice.ControllerException; import org.jbei.ice.lib.account.authentication.AuthenticationException; import org.jbei.ice.lib.account.authentication.IAuthentication; -import org.jbei.ice.lib.account.authentication.InvalidCredentialsException; -import org.jbei.ice.lib.account.authentication.LblLdapAuthentication; +import org.jbei.ice.lib.account.authentication.LocalAuthentication; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.account.model.AccountPreferences; import org.jbei.ice.lib.common.logging.Logger; @@ -20,48 +28,60 @@ import org.jbei.ice.lib.utils.Emailer; import org.jbei.ice.lib.utils.Utils; -import java.text.SimpleDateFormat; -import java.util.*; - /** * ABI to manipulate {@link Account} objects. *

- * This class contains methods that wrap {@link org.jbei.ice.lib.dao.hibernate.AccountDAO} to manipulate {@link - * Account} - * objects. + * This class contains methods that wrap {@link org.jbei.ice.lib.dao.hibernate.AccountDAO} to + * manipulate {@link Account} objects. * * @author Timothy Ham, Zinovii Dmytriv, Hector Plahar */ public class AccountController { + private static final org.slf4j.Logger log = LoggerFactory.getLogger(AccountController.class); private static final String ADMIN_ACCOUNT_EMAIL = "Administrator"; private static final String ADMIN_ACCOUNT_PASSWORD = "Administrator"; private final AccountDAO dao; private final AccountPreferencesDAO accountPreferencesDAO; + /** + * Default constructor. + */ public AccountController() { dao = DAOFactory.getAccountDAO(); accountPreferencesDAO = DAOFactory.getAccountPreferencesDAO(); } - public AccountTransfer updateAccount(String requester, long userId, AccountTransfer transfer) { - Account account = dao.get(userId); - if (!account.getEmail().equalsIgnoreCase(requester) && !isAdministrator(requester)) + /** + * @param requester + * @param userId + * @param transfer + * @return updated account object + */ + public AccountTransfer updateAccount(final String requester, final long userId, + final AccountTransfer transfer) { + final Account account = dao.get(userId); + if (!account.getEmail().equalsIgnoreCase(requester) && !isAdministrator(requester)) { return null; + } // if transfer has password then it is a password change - if (!StringUtils.isEmpty(transfer.getFirstName())) + if (!StringUtils.isEmpty(transfer.getFirstName())) { account.setFirstName(transfer.getFirstName()); + } - if (!StringUtils.isEmpty(transfer.getLastName())) + if (!StringUtils.isEmpty(transfer.getLastName())) { account.setLastName(transfer.getLastName()); + } - if (!StringUtils.isEmpty(transfer.getDescription())) + if (!StringUtils.isEmpty(transfer.getDescription())) { account.setDescription(transfer.getDescription()); + } - if (!StringUtils.isEmpty(transfer.getInstitution())) + if (!StringUtils.isEmpty(transfer.getInstitution())) { account.setInstitution(transfer.getInstitution()); + } return dao.update(account).toDataTransferObject(); } @@ -69,58 +89,71 @@ public AccountTransfer updateAccount(String requester, long userId, AccountTrans /** * Retrieve account from the database by database id. * - * @param id Database id of account + * @param id + * Database id of account * @return Account for the id */ - public Account get(long id) { + public Account get(final long id) { return dao.get(id); } /** * Reset a user's password * - * @param targetEmail email address of user account to be changed - * @return true if the user account is found with email specified in the parameter and password for it is - * successfully reset, false otherwise + * @param targetEmail + * email address of user account to be changed + * @return true if the user account is found with email specified in the parameter and password + * for it is successfully reset, false otherwise */ - public boolean resetPassword(String targetEmail) { + public boolean resetPassword(final String targetEmail) { Account account = getByEmail(targetEmail); - if (account == null) + if (account == null) { return false; + } try { - String newPassword = Utils.generateUUID().substring(24); - String encryptedNewPassword = AccountUtils.encryptNewUserPassword(newPassword, account.getSalt()); + final String newPassword = Utils.generateUUID().substring(24); + final String encryptedNewPassword = AccountUtils.encryptNewUserPassword(newPassword, + account.getSalt()); account.setPassword(encryptedNewPassword); account = dao.update(account); - AccountTransfer transfer = account.toDataTransferObject(); + final AccountTransfer transfer = account.toDataTransferObject(); transfer.setPassword(newPassword); - String url = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); + final String url = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); String projectName = Utils.getConfigValue(ConfigurationKey.PROJECT_NAME); - if (StringUtils.isEmpty(projectName)) + if (StringUtils.isEmpty(projectName)) { projectName = "ICE"; - String subject = projectName + " Password Reset"; + } + final String subject = projectName + " Password Reset"; String name = account.getFirstName(); if (StringUtils.isBlank(name)) { name = account.getLastName(); } - SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d, yyyy 'at' HH:mm aaa, z"); - - StringBuilder builder = new StringBuilder(); - builder.append("Dear ").append(name).append(",\n\n") - .append("The password for your ").append(projectName) - .append(" account (").append(targetEmail).append(") was reset on ") - .append(dateFormat.format(new Date())).append(".\nYour new temporary password is\n\n") - .append(newPassword).append("\n\n") - .append("Please go to the following link to login and change your password.\n\n") - .append("https://").append(url).append("/profile/").append(account.getId()) - .append("\n\nThank you."); + final SimpleDateFormat dateFormat = new SimpleDateFormat( + "EEE, MMM d, yyyy 'at' HH:mm aaa, z"); + + final StringBuilder builder = new StringBuilder(); + builder.append("Dear ") + .append(name) + .append(",\n\n") + .append("The password for your ") + .append(projectName) + .append(" account (") + .append(targetEmail) + .append(") was reset on ") + .append(dateFormat.format(new Date())) + .append(".\nYour new temporary password is\n\n") + .append(newPassword) + .append("\n\n") + .append("Please go to the following link to login and change your password.\n\n") + .append("https://").append(url).append("/profile/").append(account.getId()) + .append("\n\nThank you."); Emailer.send(account.getEmail(), subject, builder.toString()); - } catch (Exception ex) { + } catch (final Exception ex) { Logger.error(ex); return false; } @@ -130,34 +163,47 @@ public boolean resetPassword(String targetEmail) { /** * Updates account password associated the account email. It encrypts it before associating it * with the account + * + * @param userId + * @param transfer + * @return updated account object */ - public AccountTransfer updatePassword(String userId, AccountTransfer transfer) { - Account userAccount = getByEmail(transfer.getEmail()); - if (userAccount == null) - throw new IllegalArgumentException("Could not retrieve account by id " + transfer.getEmail()); + public AccountTransfer updatePassword(final String userId, final AccountTransfer transfer) { + final Account userAccount = getByEmail(transfer.getEmail()); + if (userAccount == null) { + throw new IllegalArgumentException("Could not retrieve account by id " + + transfer.getEmail()); + } - if (!isAdministrator(userId) && !userAccount.getEmail().equalsIgnoreCase(userId)) + if (!isAdministrator(userId) && !userAccount.getEmail().equalsIgnoreCase(userId)) { return null; + } - userAccount.setPassword(AccountUtils.encryptNewUserPassword(transfer.getPassword(), userAccount.getSalt())); + userAccount.setPassword(AccountUtils.encryptNewUserPassword(transfer.getPassword(), + userAccount.getSalt())); return dao.update(userAccount).toDataTransferObject(); } /** - * validates the account dto to ensure that the fields required (especially by the database) - * are present + * validates the account dto to ensure that the fields required (especially by the database) are + * present * - * @param accountTransfer account dto for validation + * @param accountTransfer + * account dto for validation */ - private boolean validateRequiredAccountFields(AccountTransfer accountTransfer) { - if (accountTransfer.getFirstName() == null || accountTransfer.getFirstName().trim().isEmpty()) + private boolean validateRequiredAccountFields(final AccountTransfer accountTransfer) { + if (accountTransfer.getFirstName() == null + || accountTransfer.getFirstName().trim().isEmpty()) { return false; + } - if (accountTransfer.getLastName() == null || accountTransfer.getLastName().trim().isEmpty()) + if (accountTransfer.getLastName() == null || accountTransfer.getLastName().trim().isEmpty()) { return false; + } - if (accountTransfer.getEmail() == null || accountTransfer.getEmail().trim().isEmpty()) + if (accountTransfer.getEmail() == null || accountTransfer.getEmail().trim().isEmpty()) { return false; + } return true; } @@ -166,26 +212,28 @@ private boolean validateRequiredAccountFields(AccountTransfer accountTransfer) { * Creates a new account using the parameters passed. A random password is initially generated , * encrypted and assigned to the account * - * @param info contains information needed to create account - * @param sendEmail whether to send account information (including password by email) + * @param info + * contains information needed to create account + * @param sendEmail + * whether to send account information (including password by email) * @return generated password */ - public AccountTransfer createNewAccount(AccountTransfer info, boolean sendEmail) { + public AccountTransfer createNewAccount(final AccountTransfer info, final boolean sendEmail) { // validate fields required by the database validateRequiredAccountFields(info); - String email = info.getEmail().trim(); + final String email = info.getEmail().trim(); if (getByEmail(email) != null) { Logger.error("Account with id \"" + email + "\" already exists"); return null; } // generate salt and encrypt password before storing - String salt = Utils.generateSaltForUserAccount(); - String newPassword = Utils.generateUUID().substring(24); - String encryptedPassword = AccountUtils.encryptNewUserPassword(newPassword, salt); + final String salt = Utils.generateSaltForUserAccount(); + final String newPassword = Utils.generateUUID().substring(24); + final String encryptedPassword = AccountUtils.encryptNewUserPassword(newPassword, salt); - Account account = AccountUtils.fromDTO(info); + final Account account = AccountUtils.fromDTO(info); account.setPassword(encryptedPassword); account.setSalt(salt); account.setCreationTime(Calendar.getInstance().getTime()); @@ -196,24 +244,25 @@ public AccountTransfer createNewAccount(AccountTransfer info, boolean sendEmail) return info; } - String subject = "Account created successfully"; - StringBuilder stringBuilder = new StringBuilder(); + final String subject = "Account created successfully"; + final StringBuilder stringBuilder = new StringBuilder(); String name = account.getFirstName(); if (StringUtils.isBlank(name)) { name = account.getLastName(); - if (StringUtils.isBlank(name)) + if (StringUtils.isBlank(name)) { name = email; + } } stringBuilder.append("Dear ").append(name).append(", ") - .append("\n\nThank you for creating a ") - .append(Utils.getConfigValue(ConfigurationKey.PROJECT_NAME)) - .append(" account. \nBy accessing ") - .append("this site with the password provided at the bottom ") - .append("you agree to the following terms:\n\n"); + .append("\n\nThank you for creating a ") + .append(Utils.getConfigValue(ConfigurationKey.PROJECT_NAME)) + .append(" account. \nBy accessing ") + .append("this site with the password provided at the bottom ") + .append("you agree to the following terms:\n\n"); - String terms = "Biological Parts IP Disclaimer: \n\n" + final String terms = "Biological Parts IP Disclaimer: \n\n" + "The JBEI Registry of Biological Parts Software is licensed under a standard BSD\n" + "license. Permission or license to use the biological parts registered in\n" + "the JBEI Registry of Biological Parts is not included in the BSD license\n" @@ -222,26 +271,28 @@ public AccountTransfer createNewAccount(AccountTransfer info, boolean sendEmail) + "Biological Parts will not infringe any patent or other proprietary right."; stringBuilder.append(terms); - stringBuilder.append("\n\nYour new password is: ") - .append(newPassword) - .append("\nYour login id is: ") - .append(info.getEmail()) - .append("\n\n"); + stringBuilder.append("\n\nYour new password is: ").append(newPassword) + .append("\nYour login id is: ").append(info.getEmail()).append("\n\n"); - String server = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); - stringBuilder.append("Please remember to change your password by going to your profile page at \n\n") - .append("https://").append(server).append("/profile/").append(account.getId()) - .append("\n\nThank you."); + final String server = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); + stringBuilder + .append("Please remember to change your password by going to your profile page at \n\n") + .append("https://").append(server).append("/profile/").append(account.getId()) + .append("\n\nThank you."); Emailer.send(info.getEmail(), subject, stringBuilder.toString()); info.setPassword(newPassword); return info; } + /** + * @return new admin account + */ public Account createAdminAccount() { Account adminAccount = getByEmail(ADMIN_ACCOUNT_EMAIL); - if (adminAccount != null) + if (adminAccount != null) { return adminAccount; + } adminAccount = new Account(); adminAccount.setEmail(ADMIN_ACCOUNT_EMAIL); @@ -250,11 +301,12 @@ public Account createAdminAccount() { adminAccount.setInitials(""); adminAccount.setInstitution(""); adminAccount.setSalt(Utils.generateSaltForUserAccount()); - adminAccount.setPassword(AccountUtils.encryptNewUserPassword(ADMIN_ACCOUNT_PASSWORD, adminAccount.getSalt())); + adminAccount.setPassword(AccountUtils.encryptNewUserPassword(ADMIN_ACCOUNT_PASSWORD, + adminAccount.getSalt())); adminAccount.setDescription("Administrator Account"); adminAccount.setIp(""); - Date currentTime = Calendar.getInstance().getTime(); + final Date currentTime = Calendar.getInstance().getTime(); adminAccount.setCreationTime(currentTime); adminAccount.setModificationTime(currentTime); adminAccount.setLastLoginTime(currentTime); @@ -265,22 +317,35 @@ public Account createAdminAccount() { /** * Retrieve {@link Account} by user id. * - * @param email unique identifier for account, typically email + * @param email + * unique identifier for account, typically email * @return {@link Account} */ - public Account getByEmail(String email) { + public Account getByEmail(final String email) { return dao.getByEmail(email); } - public long getAccountId(String email) { - Account account = dao.getByEmail(email); - if (account == null) + /** + * @param email + * an account identifier (usually email) + * @return database identifier of account matching account identifier (email) + * @throws IllegalArgumentException + * for an invalid account identifier + */ + public long getAccountId(final String email) { + final Account account = dao.getByEmail(email); + if (account == null) { throw new IllegalArgumentException("No account found with email " + email); + } return account.getId(); } - public Account getAccountBySessionKey(String sessionKey) { - String userId = SessionHandler.getUserIdBySession(sessionKey); + /** + * @param sessionKey + * @return Account object matching a session key, or {@code null} + */ + public Account getAccountBySessionKey(final String sessionKey) { + final String userId = SessionHandler.getUserIdBySession(sessionKey); if (userId == null) { Logger.warn("Could not retrieve user id for session " + sessionKey); return null; @@ -294,70 +359,69 @@ public Account getAccountBySessionKey(String sessionKey) { * @param account * @return {@link Account} that has been saved. */ - public Account save(Account account) { + public Account save(final Account account) { account.setModificationTime(Calendar.getInstance().getTime()); - if (account.getSalt() == null || account.getSalt().isEmpty()) + if (account.getSalt() == null || account.getSalt().isEmpty()) { account.setSalt(Utils.generateSaltForUserAccount()); + } return dao.create(account); } - public boolean isAdministrator(Account account) { + /** + * @param account + * @return {@code true} if an administrator account + */ + public boolean isAdministrator(final Account account) { return isAdministrator(account.getEmail()); } /** * Check in the database if an account is a moderator. * - * @param userId unique account identifier for user + * @param userId + * unique account identifier for user * @return True, if the account is a moderator. */ - public boolean isAdministrator(String userId) { - if (StringUtils.isEmpty(userId)) + public boolean isAdministrator(final String userId) { + if (StringUtils.isEmpty(userId)) { return false; + } - Account account = this.getByEmail(userId); + final Account account = getByEmail(userId); return account != null && account.getType() == AccountType.ADMIN; } /** * Authenticate a user in the database. *

- * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the settings file, - * authenticate - * the - * user, and return the sessionData + * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the + * settings file, authenticate the user, and return the sessionData * * @param login * @param password - * @param ip IP Address of the user. - * @throws InvalidCredentialsException + * @param ip + * IP Address of the user. + * @return the account identifier (email) on a successful login, otherwise {@code null} */ - public String authenticate(String login, String password, String ip) throws InvalidCredentialsException { - IAuthentication authentication = new LblLdapAuthentication(); + public String authenticate(final String login, final String password, final String ip) { + final IAuthentication authentication = getAuthenticationBackend(); String email; try { email = authentication.authenticates(login.trim(), password); if (email == null) { - try { - Thread.sleep(2000); // sets 2 seconds delay on login to prevent login/password brute force hacking - } catch (InterruptedException ie) { - Logger.warn(ie.getMessage()); - } + loginFailureCooldown(); return null; } - } catch (AuthenticationException e2) { - try { - Thread.sleep(2000); // sets 2 seconds delay on login to prevent login/password brute force hacking - } catch (InterruptedException ie) { - Logger.warn(ie.getMessage()); - } + } catch (final AuthenticationException e2) { + loginFailureCooldown(); return null; } - Account account = dao.getByEmail(email); + final Account account = dao.getByEmail(email); if (account != null) { - AccountPreferences accountPreferences = accountPreferencesDAO.getAccountPreferences(account); + AccountPreferences accountPreferences = accountPreferencesDAO + .getAccountPreferences(account); if (accountPreferences == null) { accountPreferences = new AccountPreferences(); @@ -375,38 +439,64 @@ public String authenticate(String login, String password, String ip) throws Inva return null; } + private void loginFailureCooldown() { + // sets 2 seconds delay on login to prevent login/password brute force hacking + try { + Thread.sleep(2000); + } catch (final InterruptedException ie) { + Logger.warn(ie.getMessage()); + } + } + + /** + * Attempts to load the ICE Authentication Backend from database configuration. + * + * @return an IAuthentication backend + */ + public IAuthentication getAuthenticationBackend() { + final String clazzName = Utils.getConfigValue(ConfigurationKey.AUTHENTICATION_BACKEND); + try { + final Class clazz = Class.forName(clazzName); + if (IAuthentication.class.isAssignableFrom(clazz)) { + return (IAuthentication) clazz.newInstance(); + } + } catch (final ClassNotFoundException e) { + log.error("Failed to load class " + clazzName); + } catch (final InstantiationException e) { + log.error("Failed to instantiate class " + clazzName); + } catch (final IllegalAccessException e) { + log.error("Inaccessible class " + clazzName); + } + return new LocalAuthentication(); + } + /** * Authenticate a user in the database. *

- * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the settings file, - * authenticate - * the - * user, and return the sessionData + * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the + * settings file, authenticate the user, and return the sessionData * - * @param transfer user information containing the email and password to be used for authentication - * If the sessionId field is set, it may or may not be used as the user's session id + * @param transfer + * user information containing the email and password to be used for authentication + * If the sessionId field is set, it may or may not be used as the user's session id * @return {@link AccountTransfer} */ - public AccountTransfer authenticate(AccountTransfer transfer) { - String email; - try { - email = authenticate(transfer.getEmail(), transfer.getPassword(), ""); - } catch (InvalidCredentialsException e) { - Logger.error(e); - return null; - } + public AccountTransfer authenticate(final AccountTransfer transfer) { + final String email = authenticate(transfer.getEmail(), transfer.getPassword(), ""); - if (email == null) + if (email == null) { return null; + } - Account account = dao.getByEmail(email); - if (account == null) + final Account account = dao.getByEmail(email); + if (account == null) { return null; + } - AccountTransfer info = account.toDataTransferObject(); + final AccountTransfer info = account.toDataTransferObject(); info.setLastLogin(account.getLastLoginTime().getTime()); info.setId(account.getId()); - boolean isAdmin = isAdministrator(email); + final boolean isAdmin = isAdministrator(email); info.setAdmin(isAdmin); info.setSessionId(SessionHandler.createSessionForUser(email, transfer.getSessionId())); return info; @@ -415,19 +505,21 @@ public AccountTransfer authenticate(AccountTransfer transfer) { /** * See if the given sessionKey is still authenticated with the system. * - * @param sessionKey unique session identifier + * @param sessionKey + * unique session identifier * @return True if sessionKey is still authenticated (active) to the system. */ - public static boolean isAuthenticated(String sessionKey) { + public static boolean isAuthenticated(final String sessionKey) { return SessionHandler.isValidSession(sessionKey); } /** * De-authenticate the given sessionKey. The user is logged out from the system. * - * @param sessionKey unique session identifier + * @param sessionKey + * unique session identifier */ - public void invalidate(String sessionKey) { + public void invalidate(final String sessionKey) { SessionHandler.invalidateSession(sessionKey); } @@ -436,16 +528,24 @@ public void invalidate(String sessionKey) { * * @param accountPreferences */ - public void saveAccountPreferences(AccountPreferences accountPreferences) { + public void saveAccountPreferences(final AccountPreferences accountPreferences) { accountPreferencesDAO.create(accountPreferences); } - public ArrayList getMatchingAccounts(String userId, String query, int limit) { - Account account = getByEmail(userId); - Set matches = dao.getMatchingAccounts(query, limit); - ArrayList result = new ArrayList<>(); - for (Account match : matches) { - AccountTransfer info = new AccountTransfer(); + /** + * @param userId + * @param query + * @param limit + * @return accounts matching the query + */ + public List getMatchingAccounts(final String userId, final String query, + final int limit) { + // TODO account object is never used? + getByEmail(userId); + final Set matches = dao.getMatchingAccounts(query, limit); + final ArrayList result = new ArrayList<>(); + for (final Account match : matches) { + final AccountTransfer info = new AccountTransfer(); info.setEmail(match.getEmail()); info.setFirstName(match.getFirstName()); info.setLastName(match.getLastName()); @@ -454,43 +554,61 @@ public ArrayList getMatchingAccounts(String userId, String quer return result; } - public AccountResults retrieveAccounts(String userId, int start, int limit, String sort, boolean asc) { + /** + * @param userId + * @param start + * @param limit + * @param sort + * @param asc + * @return window of results to all accounts + */ + public AccountResults retrieveAccounts(final String userId, final int start, final int limit, + final String sort, final boolean asc) { if (!isAdministrator(userId)) { - Logger.warn(userId + " attempting to retrieve all user accounts without admin privileges"); + Logger.warn(userId + + " attempting to retrieve all user accounts without admin privileges"); return null; } - AccountResults results = new AccountResults(); - EntryController entryController = new EntryController(); - List accounts = dao.getAccounts(start, limit, sort, asc); + final AccountResults results = new AccountResults(); + final EntryController entryController = new EntryController(); + final List accounts = dao.getAccounts(start, limit, sort, asc); - ArrayList infos = new ArrayList<>(); - for (Account userAccount : accounts) { - AccountTransfer info = userAccount.toDataTransferObject(); - long count = entryController.getNumberOfOwnerEntries(userId, userAccount.getEmail()); + final List infos = new ArrayList<>(); + for (final Account userAccount : accounts) { + final AccountTransfer info = userAccount.toDataTransferObject(); + final long count = entryController.getNumberOfOwnerEntries(userId, + userAccount.getEmail()); info.setUserEntryCount(count); info.setAdmin(isAdministrator(userAccount.getEmail())); infos.add(info); } results.getResults().addAll(infos); - long count = dao.getAccountsCount(); + final long count = dao.getAccountsCount(); results.setResultCount(count); return results; } - public void removeMemberFromGroup(long id, String email) throws ControllerException { - Account account = getByEmail(email); - if (account == null) + /** + * @param id + * @param email + * @throws ControllerException + */ + public void removeMemberFromGroup(final long id, final String email) throws ControllerException { + final Account account = getByEmail(email); + if (account == null) { throw new ControllerException("Could not find account " + email); + } - Group group = DAOFactory.getGroupDAO().get(id); - if (group == null) + final Group group = DAOFactory.getGroupDAO().get(id); + if (group == null) { throw new ControllerException("Could not find group " + id); + } account.getGroups().remove(group); try { dao.update(account); - } catch (DAOException e) { + } catch (final DAOException e) { throw new ControllerException(e); } } diff --git a/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java b/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java index 52ced75d9..b5f6359f1 100755 --- a/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java +++ b/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java @@ -35,7 +35,9 @@ public enum ConfigurationKey implements IDataTransferModel { PASSWORD_CHANGE_ALLOWED("YES"), PROFILE_EDIT_ALLOWED("YES"), JOIN_WEB_OF_REGISTRIES("NO"), - WEB_OF_REGISTRIES_MASTER("registry.jbei.org"); + WEB_OF_REGISTRIES_MASTER("registry.jbei.org"), + + AUTHENTICATION_BACKEND("org.jbei.ice.lib.account.authentication.LocalAuthentication"); private String defaultValue; diff --git a/src/main/java/org/jbei/ice/services/rest/UserResource.java b/src/main/java/org/jbei/ice/services/rest/UserResource.java index 5ad91f815..05faa8861 100644 --- a/src/main/java/org/jbei/ice/services/rest/UserResource.java +++ b/src/main/java/org/jbei/ice/services/rest/UserResource.java @@ -79,7 +79,7 @@ public AccountResults get(@DefaultValue("0") @QueryParam("offset") final int off @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") - public ArrayList getAutoCompleteForAvailableAccounts( + public List getAutoCompleteForAvailableAccounts( @QueryParam("val") final String val, @DefaultValue("8") @QueryParam("limit") final int limit) { final String userId = getUserId(); From 2aee3af5b1932a9f410f775ea698fa43357c106b Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 16 Apr 2015 17:32:56 -0700 Subject: [PATCH 15/67] Was using relative path to build HMAC signature, need to use absolute URI path --- .../jbei/ice/services/rest/AuthenticationInterceptor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java index 32b2415ed..3dc3e4174 100644 --- a/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java +++ b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java @@ -115,10 +115,13 @@ public void filter(final ContainerRequestContext requestContext) throws IOExcept } else { final UriInfo uriInfo = requestContext.getUriInfo(); final MultivaluedMap params = uriInfo.getQueryParameters(false); - final HmacSignature sig = AUTHORIZOR.initSignature(hmac, requestContext.getMethod(), - requestContext.getHeaderString("Host"), uriInfo.getPath(), params); + final String method = requestContext.getMethod(); + final String host = requestContext.getHeaderString("Host"); + final String path = uriInfo.getAbsolutePath().getPath(); // uriInfo path is relative + final HmacSignature sig = AUTHORIZOR.initSignature(hmac, method, host, path, params); requestContext.setProperty(HMAC_SIGNATURE, sig); requestContext.setProperty(EXPECTED_SIGNATURE, parts[3]); + } } From b7ed8a2dead6882e001e3d622efe95ee40571d25 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Sun, 7 Jun 2015 12:32:03 -0700 Subject: [PATCH 16/67] Adding correct generics to RestClient --- .../org/jbei/ice/services/rest/IceRestClient.java | 11 ++++++----- .../java/org/jbei/ice/services/rest/RestClient.java | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/IceRestClient.java b/src/main/java/org/jbei/ice/services/rest/IceRestClient.java index 01d31d8de..a6ca7ad5e 100644 --- a/src/main/java/org/jbei/ice/services/rest/IceRestClient.java +++ b/src/main/java/org/jbei/ice/services/rest/IceRestClient.java @@ -10,7 +10,6 @@ import javax.ws.rs.client.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.util.HashMap; import java.util.Map; /** @@ -36,12 +35,13 @@ protected IceRestClient() { client = ClientBuilder.newClient(clientConfig); } - public Object get(String url, String path, Class clazz) { + public T get(String url, String path, Class clazz) { WebTarget target = client.target("https://" + url).path(path); return target.request(MediaType.APPLICATION_JSON_TYPE).buildGet().invoke(clazz); } - public Object get(String url, String path, Class clazz, HashMap queryParams) { + @Override + public T get(String url, String path, Class clazz, Map queryParams) { WebTarget target = client.target("https://" + url).path(path); if (queryParams != null) { for (Map.Entry entry : queryParams.entrySet()) { @@ -56,7 +56,8 @@ public Object get(String url, String path) { return target.request(MediaType.APPLICATION_JSON_TYPE).buildGet().invoke(); } - public Object post(String url, String resourcePath, Object object, Class responseClass) { + @Override + public T post(String url, String resourcePath, Object object, Class responseClass) { WebTarget target = client.target("https://" + url).path(resourcePath); Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON_TYPE); Response postResponse = invocationBuilder.post(Entity.entity(object, MediaType.APPLICATION_JSON_TYPE)); @@ -65,7 +66,7 @@ public Object post(String url, String resourcePath, Object object, Class resp return null; } - public Object put(String url, String resourcePath, Object object, Class responseClass) { + public T put(String url, String resourcePath, Object object, Class responseClass) { WebTarget target = client.target("https://" + url).path(resourcePath); Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON_TYPE); Response putResponse = invocationBuilder.put(Entity.entity(object, MediaType.APPLICATION_JSON_TYPE)); diff --git a/src/main/java/org/jbei/ice/services/rest/RestClient.java b/src/main/java/org/jbei/ice/services/rest/RestClient.java index 021108b23..30a5f8445 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestClient.java +++ b/src/main/java/org/jbei/ice/services/rest/RestClient.java @@ -1,6 +1,6 @@ package org.jbei.ice.services.rest; -import java.util.HashMap; +import java.util.Map; /** * Parent Rest Client class @@ -12,7 +12,7 @@ public abstract class RestClient { protected final String AUTHENTICATION_PARAM_NAME = "X-ICE-Authentication-SessionId"; protected final String WOR_PARTNER_TOKEN_HEADER = "X-ICE-WOR-Token"; - public abstract Object get(String url, String path, Class clazz, HashMap queryParams); + public abstract T get(String url, String path, Class clazz, Map queryParams); - public abstract Object post(String url, String resourcePath, Object object, Class responseClass); + public abstract T post(String url, String resourcePath, Object object, Class responseClass); } From 1cb4b7d993aa61dfb94b8c88fc5b6ded936e9dc4 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Sun, 7 Jun 2015 12:45:53 -0700 Subject: [PATCH 17/67] Update code using RestClient to use generic type information rather than type-casting; return List instead of ArrayList from some methods --- .../ice/lib/net/RemoteAccessController.java | 28 ++++++++++--------- .../org/jbei/ice/lib/net/RemoteContact.java | 2 +- .../org/jbei/ice/lib/net/RemoteEntries.java | 17 +++++------ .../jbei/ice/lib/net/WebOfRegistriesTask.java | 4 +-- .../services/rest/RemoteAccessResource.java | 8 ++++-- .../jbei/ice/services/rest/WebResource.java | 5 +++- 6 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java b/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java index a75be5941..52d218f7f 100644 --- a/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java +++ b/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java @@ -1,6 +1,7 @@ package org.jbei.ice.lib.net; import org.apache.commons.lang.StringUtils; + import org.jbei.ice.lib.access.RemotePermission; import org.jbei.ice.lib.account.AccountTransfer; import org.jbei.ice.lib.common.logging.Logger; @@ -26,6 +27,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.UUID; /** @@ -63,7 +65,7 @@ public ArrayList getAvailableFolders(long partnerId) { try { String restPath = "/rest/folders/public"; - return (ArrayList) iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); + return iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); } catch (Exception e) { Logger.error(e); return null; @@ -76,7 +78,7 @@ public Setting getMasterVersion() { return new Setting("version", ConfigurationKey.APPLICATION_VERSION.getDefaultValue()); // retrieve version - return (Setting) iceRestClient.get(value, "/rest/config/version"); + return iceRestClient.get(value, "/rest/config/version", Setting.class); } public void addPermission(String requester, RemoteAccessPermission permission) { @@ -116,11 +118,11 @@ public AccountTransfer getRemoteUser(long remoteId, String email) { if (partner == null) return null; - Object result = iceRestClient.get(partner.getUrl(), "/rest/users/" + email, AccountTransfer.class); + AccountTransfer result = iceRestClient.get(partner.getUrl(), "/rest/users/" + email, AccountTransfer.class); if (result == null) return null; - return (AccountTransfer) result; + return result; } public FolderDetails getPublicFolderEntries(long remoteId, long folderId, String sort, boolean asc, int offset, @@ -136,33 +138,33 @@ public FolderDetails getPublicFolderEntries(long remoteId, long folderId, String queryParams.put("limit", limit); queryParams.put("asc", asc); queryParams.put("sort", sort); - Object result = iceRestClient.get(partner.getUrl(), restPath, FolderDetails.class, queryParams); + FolderDetails result = iceRestClient.get(partner.getUrl(), restPath, FolderDetails.class, queryParams); if (result == null) return null; - return (FolderDetails) result; + return result; } catch (Exception e) { Logger.error("Error getting public folder entries from \"" + partner.getUrl() + "\": " + e.getMessage()); return null; } } - public ArrayList getRemotePartSamples(long remoteId, long partId) { + public List getRemotePartSamples(long remoteId, long partId) { RemotePartner partner = this.remotePartnerDAO.get(remoteId); if (partner == null) return null; String restPath = "/rest/parts/" + partId + "/samples"; - return (ArrayList) iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); + return iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); } - public ArrayList getRemotePartComments(long remoteId, long partId) { + public List getRemotePartComments(long remoteId, long partId) { RemotePartner partner = this.remotePartnerDAO.get(remoteId); if (partner == null) return null; String restPath = "/rest/parts/" + partId + "/comments"; - return (ArrayList) iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); + return iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); } public void transferEntries(String userId, long remoteId, EntrySelection selection) { @@ -188,18 +190,18 @@ public FeaturedDNASequence getRemoteSequence(long remoteId, long partId) { } } - public ArrayList getRemoteTraces(long remoteId, long partId) { + public List getRemoteTraces(long remoteId, long partId) { RemotePartner partner = this.remotePartnerDAO.get(remoteId); if (partner == null) return null; try { String restPath = "/rest/parts/" + partId + "/traces"; - Object result = iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); + ArrayList result = iceRestClient.get(partner.getUrl(), restPath, ArrayList.class); if (result == null) return null; - return (ArrayList) result; + return result; } catch (Exception e) { Logger.error(e.getMessage()); return null; diff --git a/src/main/java/org/jbei/ice/lib/net/RemoteContact.java b/src/main/java/org/jbei/ice/lib/net/RemoteContact.java index 874ce4620..c39b66042 100644 --- a/src/main/java/org/jbei/ice/lib/net/RemoteContact.java +++ b/src/main/java/org/jbei/ice/lib/net/RemoteContact.java @@ -187,7 +187,7 @@ protected boolean apiKeyValidates(String myURL, RegistryPartner registryPartner) HashMap queryParams = new HashMap<>(); queryParams.put("url", myURL); - RegistryPartner response = (RegistryPartner) restClient.get(registryPartner.getUrl(), "/accesstoken/web", + RegistryPartner response = restClient.get(registryPartner.getUrl(), "/accesstoken/web", RegistryPartner.class, queryParams); if (response == null) { // todo : should retry up to a certain number of times Logger.error("Could not validate request"); diff --git a/src/main/java/org/jbei/ice/lib/net/RemoteEntries.java b/src/main/java/org/jbei/ice/lib/net/RemoteEntries.java index 57c1455a1..28b86a74e 100644 --- a/src/main/java/org/jbei/ice/lib/net/RemoteEntries.java +++ b/src/main/java/org/jbei/ice/lib/net/RemoteEntries.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** * Entries that are on other registry instances other than this instance. @@ -64,7 +65,7 @@ public WebEntries getPublicEntries(String userId, long remoteId, int offset, int queryParams.put("limit", limit); queryParams.put("asc", asc); queryParams.put("sort", sort); - details = (FolderDetails) iceRestClient.get(partner.getUrl(), restPath, FolderDetails.class, queryParams); + details = iceRestClient.get(partner.getUrl(), restPath, FolderDetails.class, queryParams); if (details == null) return null; } catch (Exception e) { @@ -80,7 +81,7 @@ public WebEntries getPublicEntries(String userId, long remoteId, int offset, int } @SuppressWarnings("unchecked") - public ArrayList getEntryAttachments(String userId, long remoteId, long entryId) { + public List getEntryAttachments(String userId, long remoteId, long entryId) { if (!hasRemoteAccessEnabled()) return null; @@ -89,7 +90,7 @@ public ArrayList getEntryAttachments(String userId, long remoteI return null; String path = "/rest/parts/" + entryId + "/attachments"; - return (ArrayList) iceRestClient.get(partner.getUrl(), path, ArrayList.class); + return iceRestClient.get(partner.getUrl(), path, ArrayList.class); } public FeaturedDNASequence getEntrySequence(String userId, long remoteId, long entryId) { @@ -101,7 +102,7 @@ public FeaturedDNASequence getEntrySequence(String userId, long remoteId, long e return null; String path = "/rest/parts/" + entryId + "/sequence"; - return (FeaturedDNASequence) iceRestClient.get(partner.getUrl(), path, FeaturedDNASequence.class); + return iceRestClient.get(partner.getUrl(), path, FeaturedDNASequence.class); } public void transferEntries(String userId, long remoteId, EntrySelection selection) { @@ -117,7 +118,7 @@ public PartData getPublicEntry(String userId, long remoteId, long entryId) { if (partner == null || partner.getPartnerStatus() != RemotePartnerStatus.APPROVED) return null; - return (PartData) iceRestClient.get(partner.getUrl(), "/rest/parts/" + entryId, PartData.class); + return iceRestClient.get(partner.getUrl(), "/rest/parts/" + entryId, PartData.class); } public PartData getPublicEntryTooltip(String userId, long remoteId, long entryId) { @@ -129,7 +130,7 @@ public PartData getPublicEntryTooltip(String userId, long remoteId, long entryId return null; String path = "/rest/parts/" + entryId + "/tooltip"; - return (PartData) iceRestClient.get(partner.getUrl(), path, PartData.class); + return iceRestClient.get(partner.getUrl(), path, PartData.class); } public PartStatistics getPublicEntryStatistics(String userId, long remoteId, long entryId) { @@ -141,7 +142,7 @@ public PartStatistics getPublicEntryStatistics(String userId, long remoteId, lon return null; String path = "/rest/parts/" + entryId + "/statistics"; - return (PartStatistics) iceRestClient.get(partner.getUrl(), path, PartStatistics.class); + return iceRestClient.get(partner.getUrl(), path, PartStatistics.class); } public FeaturedDNASequence getPublicEntrySequence(String userId, long remoteId, long entryId) { @@ -153,7 +154,7 @@ public FeaturedDNASequence getPublicEntrySequence(String userId, long remoteId, return null; String path = "/rest/parts/" + entryId + "/sequence"; - return (FeaturedDNASequence) iceRestClient.get(partner.getUrl(), path, FeaturedDNASequence.class); + return iceRestClient.get(partner.getUrl(), path, FeaturedDNASequence.class); } public File getPublicAttachment(String userId, long remoteId, String fileId) { diff --git a/src/main/java/org/jbei/ice/lib/net/WebOfRegistriesTask.java b/src/main/java/org/jbei/ice/lib/net/WebOfRegistriesTask.java index ef3732f05..99546e4b2 100644 --- a/src/main/java/org/jbei/ice/lib/net/WebOfRegistriesTask.java +++ b/src/main/java/org/jbei/ice/lib/net/WebOfRegistriesTask.java @@ -75,13 +75,13 @@ public void execute() { // contacts the master node for other ice instances protected RegistryPartner requestToJoin(String masterUrl, RegistryPartner partner) { IceRestClient restClient = IceRestClient.getInstance(); - return (RegistryPartner) restClient.post(masterUrl, "/rest/web/partner/remote", partner, RegistryPartner.class); + return restClient.post(masterUrl, "/rest/web/partner/remote", partner, RegistryPartner.class); } @SuppressWarnings("unchecked") protected List getWebOfRegistryPartners(String url) { IceRestClient restClient = IceRestClient.getInstance(); - return (ArrayList) restClient.get(url, "/rest/web/partners", ArrayList.class); + return restClient.get(url, "/rest/web/partners", ArrayList.class); } /** diff --git a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java index 3358f63c5..ca0065788 100644 --- a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java @@ -1,6 +1,8 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; +import java.util.List; + import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; @@ -66,7 +68,7 @@ public Response getSequence(@PathParam("id") long remoteId, @Path("/parts/{entryId}/traces") public Response getSequenceTraces(@PathParam("id") long remoteId, @PathParam("entryId") long partId) { - ArrayList traces = controller.getRemoteTraces(remoteId, partId); + List traces = controller.getRemoteTraces(remoteId, partId); if (traces == null) return Response.status(Response.Status.NO_CONTENT).build(); return Response.status(Response.Status.OK).entity(traces).build(); @@ -92,7 +94,7 @@ public FolderDetails getPublicFolderEntries( public Response getRemotePartSamples(@PathParam("id") long remoteId, @PathParam("partId") long partId, @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - ArrayList result = controller.getRemotePartSamples(remoteId, partId); + List result = controller.getRemotePartSamples(remoteId, partId); return super.respond(result); } @@ -102,7 +104,7 @@ public Response getRemotePartSamples(@PathParam("id") long remoteId, public Response getRemotePartComments(@PathParam("id") long remoteId, @PathParam("partId") long partId, @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - ArrayList result = controller.getRemotePartComments(remoteId, partId); + List result = controller.getRemotePartComments(remoteId, partId); return super.respond(result); } } diff --git a/src/main/java/org/jbei/ice/services/rest/WebResource.java b/src/main/java/org/jbei/ice/services/rest/WebResource.java index ab00b7167..899bb3b97 100644 --- a/src/main/java/org/jbei/ice/services/rest/WebResource.java +++ b/src/main/java/org/jbei/ice/services/rest/WebResource.java @@ -1,6 +1,7 @@ package org.jbei.ice.services.rest; import org.hsqldb.lib.StringUtil; + import org.jbei.ice.lib.dto.entry.AttachmentInfo; import org.jbei.ice.lib.dto.entry.PartData; import org.jbei.ice.lib.dto.entry.PartStatistics; @@ -17,7 +18,9 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; + import java.util.ArrayList; +import java.util.List; /** * Resource for web of registries requests @@ -76,7 +79,7 @@ public Response getWebEntries( @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/attachments") - public ArrayList getAttachments( + public List getAttachments( @PathParam("id") long partnerId, @PathParam("entryId") long partId, @HeaderParam(AUTHENTICATION_PARAM_NAME) String userAgentHeader) { From 85dc3c86d202ac8cb467c4a664e955a75e6ff6d6 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Sun, 7 Jun 2015 13:09:34 -0700 Subject: [PATCH 18/67] SearchController can return incorrect results size on WoR search --- .../java/org/jbei/ice/lib/net/RemoteAccessController.java | 2 +- src/main/java/org/jbei/ice/lib/net/RemoteTransfer.java | 2 +- src/main/java/org/jbei/ice/lib/search/SearchController.java | 5 +++-- .../org/jbei/ice/services/rest/RemoteAccessResource.java | 2 +- src/main/java/org/jbei/ice/services/rest/WebResource.java | 1 - 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java b/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java index 52d218f7f..9162b89d9 100644 --- a/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java +++ b/src/main/java/org/jbei/ice/lib/net/RemoteAccessController.java @@ -58,7 +58,7 @@ public RemoteAccessController() { * null on exception */ @SuppressWarnings("unchecked") - public ArrayList getAvailableFolders(long partnerId) { + public List getAvailableFolders(long partnerId) { RemotePartner partner = this.remotePartnerDAO.get(partnerId); if (partner == null) return null; diff --git a/src/main/java/org/jbei/ice/lib/net/RemoteTransfer.java b/src/main/java/org/jbei/ice/lib/net/RemoteTransfer.java index 6c90d1831..e95dee64b 100644 --- a/src/main/java/org/jbei/ice/lib/net/RemoteTransfer.java +++ b/src/main/java/org/jbei/ice/lib/net/RemoteTransfer.java @@ -98,7 +98,7 @@ public void transferEntries(long remoteId, List entries) { for (PartData data : entries) { try { - Object object = client.put(url, "/rest/parts/transfer", data, PartData.class); + PartData object = client.put(url, "/rest/parts/transfer", data, PartData.class); if (object == null) { exceptionCount += 1; continue; diff --git a/src/main/java/org/jbei/ice/lib/search/SearchController.java b/src/main/java/org/jbei/ice/lib/search/SearchController.java index b2179976b..744735c49 100755 --- a/src/main/java/org/jbei/ice/lib/search/SearchController.java +++ b/src/main/java/org/jbei/ice/lib/search/SearchController.java @@ -59,7 +59,7 @@ public SearchResults runWebSearch(SearchQuery query) { continue; try { - SearchResults results = (SearchResults) client.post(partner.getUrl(), "/rest/search", query, + SearchResults results = client.post(partner.getUrl(), "/rest/search", query, SearchResults.class); if (results == null) continue; @@ -70,7 +70,8 @@ public SearchResults runWebSearch(SearchQuery query) { resultsList.add(result); } - total += results.getResults().size(); + // up to 50 returned from each partner, but total size may be greater + total += results.getResultCount(); } catch (Exception e) { Logger.warn("Exception contacting partner " + partner.getUrl() + " : " + e.getMessage()); } diff --git a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java index ca0065788..a61331fcc 100644 --- a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java @@ -40,7 +40,7 @@ public class RemoteAccessResource extends RestResource { @GET @Produces(MediaType.APPLICATION_JSON) @Path("/available") - public ArrayList readRemoteUser(@PathParam("id") long remoteId) { + public List readRemoteUser(@PathParam("id") long remoteId) { return controller.getAvailableFolders(remoteId); } diff --git a/src/main/java/org/jbei/ice/services/rest/WebResource.java b/src/main/java/org/jbei/ice/services/rest/WebResource.java index 899bb3b97..23ec23968 100644 --- a/src/main/java/org/jbei/ice/services/rest/WebResource.java +++ b/src/main/java/org/jbei/ice/services/rest/WebResource.java @@ -19,7 +19,6 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; import java.util.List; /** From c5be10d9fe38c8d5c9f403545b7c2c9db5d01696 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 1 Apr 2015 18:42:31 -0700 Subject: [PATCH 19/67] Using rest-util artifact to extend RestResource to handle Hash-based Message Authentication Code (HMAC) validation in HTTP Authorization headers --- pom.xml | 5 + .../jbei/ice/services/rest/RestResource.java | 132 +++++++++++++++--- 2 files changed, 121 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index 5c580aa90..991d0507f 100755 --- a/pom.xml +++ b/pom.xml @@ -127,6 +127,11 @@ libSBOLj 0.7.0-SNAPSHOT + + org.jbei.informatics + rest-util + 1.0.0-SNAPSHOT + target diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index 066f16ee6..0272305e0 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -1,11 +1,26 @@ package org.jbei.ice.services.rest; -import org.jbei.ice.lib.account.SessionHandler; -import org.jbei.ice.lib.common.logging.Logger; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.nio.file.Paths; +import java.security.Key; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.HeaderParam; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; +import org.jbei.auth.Authorization; +import org.jbei.auth.KeyTable; +import org.jbei.auth.hmac.HmacAuthorizor; +import org.jbei.auth.hmac.HmacSignatureFactory; +import org.jbei.ice.lib.account.SessionHandler; +import org.jbei.ice.lib.common.logging.Logger; +import org.jbei.ice.lib.dto.ConfigurationKey; +import org.jbei.ice.lib.utils.Utils; + /** * Parent class for all rest resource objects * @@ -16,46 +31,131 @@ public class RestResource { protected final String AUTHENTICATION_PARAM_NAME = "X-ICE-Authentication-SessionId"; protected final String WOR_PARTNER_TOKEN = "X-ICE-WOR-Token"; - protected String getUserIdFromSessionHeader(String sessionHeader) { - String userId = SessionHandler.getUserIdBySession(sessionHeader); - if (userId == null) + // do lookup by using existing configuration DATA_DIRECTORY to find key names => key data + private static final KeyTable TABLE = new KeyTable() { + + // keys stored in /var/lib/tomcat6/data/rest-auth by default + private final File directory = Paths.get( + Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), "rest-auth").toFile(); + + @Override + public Key getKey(final String keyId) { + try { + // find file named by keyId in the directory + final File keyFile = new File(directory, keyId); + // collect all lines in the file to a buffer + final StringBuilder encoded = new StringBuilder(); + try (final FileReader reader = new FileReader(keyFile); + final BufferedReader buffered = new BufferedReader(reader);) { + String line; + while ((line = buffered.readLine()) != null) { + encoded.append(line); + } + // after reading all lines, decode value into a Key object + return HmacSignatureFactory.decodeKey(encoded.toString()); + } + } catch (final Throwable t) { + Logger.error("Failed to load rest-auth key " + keyId); + } + return null; + } + + }; + + private static final HmacAuthorizor AUTHORIZOR = new HmacAuthorizor(TABLE); + + @HeaderParam(value = "X-ICE-Authentication-SessionId") + private String sessionId; + + @HeaderParam(value = "Authorization") + private String hmacHeader; + + @Context + private HttpServletRequest request; + + private String userId = null; + + /** + * Extract the User ID from header values in the resource request. + * + * @return a string User ID + * @throws WebApplicationException + * for unauthorized access + */ + protected String getUserId() { + final Authorization auth; + if (userId != null) { + // we've already looked up the userId + return userId; + } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { + userId = auth.getUserId(); + // TODO validation of meaningful userId + // e.g. "admin" account on EDD won't mean anything to ICE + } else if (sessionId != null) { + userId = SessionHandler.getUserIdBySession(sessionId); + } + if (userId == null) { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + return userId; + } + + /** + * @param sessionHeader + * not used + * @return the UserId of the user matching the session value + * @throws WebApplicationException + * if there is no valid UserId + * @deprecated use {@link #getUserId()} instead + */ + @Deprecated + protected String getUserIdFromSessionHeader(final String sessionHeader) { + final String userId = SessionHandler.getUserIdBySession(sessionId); + if (userId == null) { throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } return userId; } - protected Response respond(Response.Status status, Object obj) { - if (obj == null) + protected Response respond(final Response.Status status, final Object obj) { + if (obj == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(status).entity(obj).build(); } - protected Response respond(Object object) { - if (object == null) + protected Response respond(final Object object) { + if (object == null) { return Response.status(Response.Status.NOT_FOUND).build(); + } return Response.status(Response.Status.OK).entity(object).build(); } - protected Response respond(Response.Status status) { + protected Response respond(final Response.Status status) { return Response.status(status).build(); } - protected Response respond(boolean success) { - if (success) + protected Response respond(final boolean success) { + if (success) { return Response.status(Response.Status.OK).build(); + } return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } /** * Used to log user actions * - * @param userId unique user identifier - * @param message log message + * @param userId + * unique user identifier + * @param message + * log message */ - protected void log(String userId, String message) { - if (userId == null) + protected void log(String userId, final String message) { + if (userId == null) { userId = "Unknown"; + } Logger.info(userId + ": " + message); } } From eed10aeb8a777962f260c53ad9ce53f388ad63c0 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 1 Apr 2015 19:03:41 -0700 Subject: [PATCH 20/67] Adding javadoc to RestResource, convert SearchResource to rely on RestResource to find user --- .../jbei/ice/services/rest/RestResource.java | 39 ++++++-- .../ice/services/rest/SearchResource.java | 88 +++++++++++-------- 2 files changed, 84 insertions(+), 43 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index 0272305e0..feaa4b0c3 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -117,6 +117,16 @@ protected String getUserIdFromSessionHeader(final String sessionHeader) { return userId; } + /** + * Create a {@link Response} object from an entity object. + * + * @param status + * HTTP status code + * @param obj + * entity in response + * @return a Response object for the resource request, uses 500 error response if entity is + * {@code null} + */ protected Response respond(final Response.Status status, final Object obj) { if (obj == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); @@ -125,6 +135,13 @@ protected Response respond(final Response.Status status, final Object obj) { return Response.status(status).entity(obj).build(); } + /** + * Create a {@link Response} object from an entity object. + * + * @param object + * entity in response + * @return a 404 NOT FOUND if object is {@code null}, else a 200 OK response with the entity + */ protected Response respond(final Object object) { if (object == null) { return Response.status(Response.Status.NOT_FOUND).build(); @@ -133,10 +150,24 @@ protected Response respond(final Object object) { return Response.status(Response.Status.OK).entity(object).build(); } + /** + * Create an empty {@link Response} object. + * + * @param status + * HTTP status code to use on the Response + * @return a Response object for the resource request + */ protected Response respond(final Response.Status status) { return Response.status(status).build(); } + /** + * Create an empty {@link Response} object. + * + * @param success + * success/failure flag + * @return a 200 OK response if success is {@code true}, otherwise a 500 error response + */ protected Response respond(final boolean success) { if (success) { return Response.status(Response.Status.OK).build(); @@ -152,10 +183,8 @@ protected Response respond(final boolean success) { * @param message * log message */ - protected void log(String userId, final String message) { - if (userId == null) { - userId = "Unknown"; - } - Logger.info(userId + ": " + message); + protected void log(final String userId, final String message) { + final String who = (userId == null) ? "Unknown" : userId; + Logger.info(who + ": " + message); } } diff --git a/src/main/java/org/jbei/ice/services/rest/SearchResource.java b/src/main/java/org/jbei/ice/services/rest/SearchResource.java index a7d17890f..1b0573600 100644 --- a/src/main/java/org/jbei/ice/services/rest/SearchResource.java +++ b/src/main/java/org/jbei/ice/services/rest/SearchResource.java @@ -1,7 +1,20 @@ package org.jbei.ice.services.rest; +import java.util.Arrays; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + import org.apache.commons.lang.StringUtils; -import org.jbei.ice.lib.account.SessionHandler; + import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.entry.EntryType; import org.jbei.ice.lib.dto.search.SearchQuery; @@ -9,15 +22,9 @@ import org.jbei.ice.lib.search.SearchController; import org.jbei.ice.lib.shared.ColumnField; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.Arrays; -import java.util.List; - /** - * REST resource for searching. Supports keyword search with query params for filtering and - * advanced search + * REST resource for searching. Supports keyword search with query params for filtering and advanced + * search * * @author Hector Plahar */ @@ -27,24 +34,26 @@ public class SearchResource extends RestResource { private SearchController controller = new SearchController(); /** - * Advanced Search. The use of post is mostly for the sequence string for - * blast which can get very long and results in a 413 status code if - * sent via GET + * Advanced Search. The use of post is mostly for the sequence string for blast which can get + * very long and results in a 413 status code if sent via GET + * + * @param searchWeb + * whether to perform a web of registry search or not + * @param query + * parameters to the search * * @return results of the search */ @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) - public Response search( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionHeader, - @DefaultValue("false") @QueryParam("webSearch") boolean searchWeb, - SearchQuery query) { - String userId = SessionHandler.getUserIdBySession(sessionHeader); + public Response search(@DefaultValue("false") @QueryParam("webSearch") final boolean searchWeb, + final SearchQuery query) { + final String userId = getUserId(); try { - SearchResults results = controller.runSearch(userId, query, searchWeb); + final SearchResults results = controller.runSearch(userId, query, searchWeb); return super.respond(Response.Status.OK, results); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return super.respond(Response.Status.INTERNAL_SERVER_ERROR); } @@ -53,41 +62,44 @@ public Response search( /** * Keyword search * - * @param queryString keywords to search on - * @param searchWeb whether to perform a web of registry search or not - * @param offset result start - * @param limit result count upper limit - * @param sort result sort - * @param asc true if return results in ascending order, false otherwise - * @param sessionId user unique session identifier + * @param queryString + * keywords to search on + * @param searchWeb + * whether to perform a web of registry search or not + * @param offset + * result start + * @param limit + * result count upper limit + * @param sort + * result sort + * @param asc + * true if return results in ascending order, false otherwise * @return wrapper around list of search results conforming to query params */ @GET @Produces(MediaType.APPLICATION_JSON) - public Response search( - @QueryParam("q") String queryString, - @DefaultValue("false") @QueryParam("webSearch") boolean searchWeb, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("relevance") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = SessionHandler.getUserIdBySession(sessionId); + public Response search(@QueryParam("q") final String queryString, + @DefaultValue("false") @QueryParam("webSearch") final boolean searchWeb, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("relevance") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { + final String userId = getUserId(); if (StringUtils.isEmpty(userId) && !searchWeb) { return super.respond(Response.Status.FORBIDDEN); } log(userId, "query \'" + queryString + '\''); - SearchQuery query = new SearchQuery(); + final SearchQuery query = new SearchQuery(); query.setQueryString(queryString); - SearchQuery.Parameters parameters = query.getParameters(); + final SearchQuery.Parameters parameters = query.getParameters(); parameters.setRetrieveCount(limit); parameters.setStart(offset); parameters.setSortAscending(asc); parameters.setSortField(ColumnField.valueOf(sort.toUpperCase())); - List types = Arrays.asList(EntryType.values()); + final List types = Arrays.asList(EntryType.values()); query.setEntryTypes(types); return super.respond(controller.runSearch(userId, query, searchWeb)); } From 8c9afbad6a7800010e2322af5be0f907a59dd99e Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 2 Apr 2015 16:09:56 -0700 Subject: [PATCH 21/67] Converting more REST resources to use parent class to find current user, adding Javadoc and fixing warnings --- .../services/rest/AccessTokenResource.java | 24 +- .../services/rest/ArrayDataJSONHandler.java | 54 +-- .../ice/services/rest/BulkUploadResource.java | 335 +++++++++++------- .../ice/services/rest/ConfigResource.java | 66 ++-- .../jbei/ice/services/rest/FileResource.java | 316 ++++++++++------- .../jbei/ice/services/rest/RestResource.java | 2 +- 6 files changed, 486 insertions(+), 311 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java b/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java index eee543624..01f993033 100644 --- a/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java +++ b/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java @@ -20,18 +20,18 @@ public class AccessTokenResource extends RestResource { private final AccountController accountController = new AccountController(); /** - * Creates a new access token for the user referenced in the parameter, after - * the credentials (username and password) are validated. If one already exists, it is - * invalidated + * Creates a new access token for the user referenced in the parameter, after the credentials + * (username and password) are validated. If one already exists, it is invalidated * - * @param transfer wraps username and password + * @param transfer + * wraps username and password * @return account information including a valid session id if credentials validate */ @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) - public Response create(AccountTransfer transfer) { - AccountTransfer info = accountController.authenticate(transfer); + public Response create(final AccountTransfer transfer) { + final AccountTransfer info = accountController.authenticate(transfer); if (info == null) { Logger.warn("Authentication failed for user " + transfer.getEmail()); return respond(Response.Status.UNAUTHORIZED); @@ -42,20 +42,20 @@ public Response create(AccountTransfer transfer) { } /** - * Invalidates the specified session information. - * - * @param sessionId session identifier to invalidates + * Invalidates the current session information. */ @DELETE - public void deleteToken(@HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - getUserIdFromSessionHeader(sessionId); + public void deleteToken() { + // ensure the user is valid + getUserId(); accountController.invalidate(sessionId); } /** * Retrieve account information for user referenced by session id * - * @param sessionId unique session identifier for logged in user + * @param sessionId + * unique session identifier for logged in user * @return account information for session if session is valid, null otherwise */ @GET diff --git a/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java b/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java index 80c7ec856..e43d9ac84 100644 --- a/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java +++ b/src/main/java/org/jbei/ice/services/rest/ArrayDataJSONHandler.java @@ -1,8 +1,15 @@ package org.jbei.ice.services.rest; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import org.jbei.ice.lib.dao.IDataTransferModel; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.ArrayList; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; @@ -12,10 +19,11 @@ import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Provider; -import java.io.*; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.ArrayList; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import org.jbei.ice.lib.dao.IDataTransferModel; /** * @author Hector Plahar @@ -24,39 +32,43 @@ @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public class ArrayDataJSONHandler implements MessageBodyWriter>, - MessageBodyReader> { + MessageBodyReader> { @Override - public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + public boolean isReadable(final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType) { return true; } @Override - public ArrayList readFrom(Class> type, Type genericType, - Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - InputStream entityStream) - throws IOException, WebApplicationException { - Gson gson = new GsonBuilder().create(); + public ArrayList readFrom(final Class> type, + final Type genericType, final Annotation[] annotations, final MediaType mediaType, + final MultivaluedMap httpHeaders, final InputStream entityStream) + throws IOException, WebApplicationException { + final Gson gson = new GsonBuilder().create(); try (Reader in = new InputStreamReader(entityStream)) { return gson.fromJson(in, type); } } @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + public boolean isWriteable(final Class type, final Type genericType, + final Annotation[] annotations, final MediaType mediaType) { return true; } @Override - public long getSize(ArrayList iDataTransferModels, Class type, Type genericType, Annotation[] - annotations, MediaType mediaType) { + public long getSize(final ArrayList iDataTransferModels, + final Class type, final Type genericType, final Annotation[] annotations, + final MediaType mediaType) { return 0; } @Override - public void writeTo(ArrayList data, Class type, Type genericType, Annotation[] annotations, - MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) - throws IOException, WebApplicationException { - Gson gson = new GsonBuilder().setPrettyPrinting().create(); + public void writeTo(final ArrayList data, final Class type, + final Type genericType, final Annotation[] annotations, final MediaType mediaType, + final MultivaluedMap httpHeaders, final OutputStream entityStream) + throws IOException, WebApplicationException { + final Gson gson = new GsonBuilder().setPrettyPrinting().create(); try (Writer out = new OutputStreamWriter(entityStream)) { gson.toJson(data, out); } diff --git a/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java b/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java index b86c74ebc..87e64c6ef 100644 --- a/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java +++ b/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java @@ -1,9 +1,32 @@ package org.jbei.ice.services.rest; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; + import org.jbei.ice.lib.access.AuthorizationException; import org.jbei.ice.lib.bulkupload.BulkEntryCreator; import org.jbei.ice.lib.bulkupload.BulkUploadController; @@ -19,18 +42,6 @@ import org.jbei.ice.lib.entry.sequence.SequenceController; import org.jbei.ice.lib.utils.Utils; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.io.File; -import java.io.InputStream; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - /** * Rest API for interacting with Bulk upload resources * @@ -42,19 +53,26 @@ public class BulkUploadResource extends RestResource { private BulkUploadController controller = new BulkUploadController(); private BulkEntryCreator creator = new BulkEntryCreator(); + /** + * @param info + * @param id + * @param offset + * @param limit + * @return model object for bulk upload + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public BulkUploadInfo read(@Context UriInfo info, @PathParam("id") long id, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("50") @QueryParam("limit") int limit, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public BulkUploadInfo read(@Context final UriInfo info, @PathParam("id") final long id, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("50") @QueryParam("limit") final int limit) { + final String userId = getUserId(); try { - Logger.info(userId + ": retrieving bulk import with id \"" + id + "\" [" + offset + ", " + limit + "]"); + Logger.info(userId + ": retrieving bulk import with id \"" + id + "\" [" + offset + + ", " + limit + "]"); return controller.getBulkImport(userId, id, offset, limit); - } catch (Exception e) { + } catch (final Exception e) { return null; } } @@ -80,87 +98,107 @@ public Response getPartNumbersForUpload( /** * Retrieves permissions associated with an upload * - * @param sessionId unique session identifier for the user making request - * @param id unique identifier for the upload + * @param id + * unique identifier for the upload * @return retrieved permissions for specified upload if user has required permissions */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public Response getUploadPermissions(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - List permissionList = controller.getUploadPermissions(userId, id); + public Response getUploadPermissions(@PathParam("id") final long id) { + final String userId = getUserId(); + final List permissionList = controller.getUploadPermissions(userId, id); return super.respond(permissionList); } /** * Add upload permission * - * @param sessionId unique session identifier for the user making request - * @param id unique identifier for the upload + * @param id + * unique identifier for the upload + * @param accessPermission + * model object for permissions applied to upload + * @return Response with the added permission */ @POST @Path("/{id}/permissions") - public Response addPermission(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - AccessPermission accessPermission) { - String userId = getUserIdFromSessionHeader(sessionId); - AccessPermission permission = controller.addPermission(userId, id, accessPermission); + public Response addPermission(@PathParam("id") final long id, + final AccessPermission accessPermission) { + final String userId = getUserId(); + final AccessPermission permission = controller.addPermission(userId, id, accessPermission); return super.respond(permission); } + /** + * @param id + * @param permissionId + * @return Response with success or failure of permissions delete + */ @DELETE @Path("/{id}/permissions/{pid}") - public Response removePermission(@PathParam("id") long id, - @PathParam("pid") long permissionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - boolean success = controller.deletePermission(userId, id, permissionId); + public Response removePermission(@PathParam("id") final long id, + @PathParam("pid") final long permissionId) { + final String userId = getUserId(); + final boolean success = controller.deletePermission(userId, id, permissionId); return super.respond(success); } + /** + * @param uploadId + * @param fileInputStream + * @param entryId + * @param contentDispositionHeader + * @return Response with sequence information if upload is successful + */ @POST @Path("/{id}/sequence") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response uploadSequenceFile(@PathParam("id") long uploadId, - @FormDataParam("file") InputStream fileInputStream, - @FormDataParam("entryId") long entryId, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response uploadSequenceFile(@PathParam("id") final long uploadId, + @FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("entryId") final long entryId, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - String fileName = contentDispositionHeader.getFileName(); - String userId = super.getUserIdFromSessionHeader(sessionId); - String sequence = IOUtils.toString(fileInputStream); - SequenceInfo sequenceInfo = controller.addSequence(userId, uploadId, entryId, sequence, fileName); - if (sequenceInfo == null) + final String fileName = contentDispositionHeader.getFileName(); + final String userId = getUserId(); + final String sequence = IOUtils.toString(fileInputStream); + final SequenceInfo sequenceInfo = controller.addSequence(userId, uploadId, entryId, + sequence, fileName); + if (sequenceInfo == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(Response.Status.OK).entity(sequenceInfo).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } + /** + * @param uploadId + * @param fileInputStream + * @param entryId + * @param contentDispositionHeader + * @return Response with information on attachment upload + */ @POST @Path("/{id}/attachment") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response uploadAttachmentFile(@PathParam("id") long uploadId, - @FormDataParam("file") InputStream fileInputStream, - @FormDataParam("entryId") long entryId, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response uploadAttachmentFile(@PathParam("id") final long uploadId, + @FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("entryId") final long entryId, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - String fileName = contentDispositionHeader.getFileName(); - String userId = super.getUserIdFromSessionHeader(sessionId); - AttachmentInfo attachmentInfo = controller.addAttachment(userId, uploadId, entryId, fileInputStream, - fileName); - if (attachmentInfo == null) + final String fileName = contentDispositionHeader.getFileName(); + final String userId = getUserId(); + final AttachmentInfo attachmentInfo = controller.addAttachment(userId, uploadId, + entryId, fileInputStream, fileName); + if (attachmentInfo == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(Response.Status.OK).entity(attachmentInfo).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } @@ -169,131 +207,167 @@ public Response uploadAttachmentFile(@PathParam("id") long uploadId, /** * Creates or updates a list of entries that are to be associated with the specified bulk upload * + * @param id + * @param info + * * @return wrapper around list of created or updated entries */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public BulkUploadInfo updateList(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @PathParam("id") long id, BulkUploadInfo info) { - String userId = getUserIdFromSessionHeader(sessionId); + public BulkUploadInfo updateList(@PathParam("id") final long id, final BulkUploadInfo info) { + final String userId = getUserId(); return creator.createOrUpdateEntries(userId, id, info.getEntryList()); } + /** + * @return Response with pending upload information + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/pending") - public Response getPendingUploads(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response getPendingUploads() { try { - String userId = getUserIdFromSessionHeader(sessionId); - HashMap> pending = controller.getPendingImports(userId); + final String userId = getUserId(); + final HashMap> pending = controller + .getPendingImports(userId); return Response.status(Response.Status.OK).entity(pending).build(); - } catch (AuthorizationException ae) { + } catch (final AuthorizationException ae) { return respond(Response.Status.INTERNAL_SERVER_ERROR); } } + /** + * @param id + * @param info + * @return Response with upload information on renamed upload + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/name") - public Response updateName(@PathParam("id") long id, BulkUploadInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - Logger.info(userId + ": updating bulk upload name for " + info.getId() + " with value " + info.getName()); - BulkUploadInfo result = creator.renameBulkUpload(userId, id, info.getName()); - if (result == null) + public Response updateName(@PathParam("id") final long id, final BulkUploadInfo info) { + final String userId = getUserId(); + Logger.info(userId + ": updating bulk upload name for " + info.getId() + " with value " + + info.getName()); + final BulkUploadInfo result = creator.renameBulkUpload(userId, id, info.getName()); + if (result == null) { return respond(Response.Status.INTERNAL_SERVER_ERROR); + } return respond(Response.Status.OK, result); } + /** + * @param id + * @param info + * @return Response with updated bulk upload info + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/status") - public Response updateStatus( - @PathParam("id") long id, - BulkUploadInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - Logger.info(userId + ": updating bulk upload status for " + info.getId() + " to " + info.getStatus()); - BulkUploadInfo resp = creator.updateStatus(userId, id, info.getStatus()); - if (resp == null) + public Response updateStatus(@PathParam("id") final long id, final BulkUploadInfo info) { + final String userId = getUserId(); + Logger.info(userId + ": updating bulk upload status for " + info.getId() + " to " + + info.getStatus()); + final BulkUploadInfo resp = creator.updateStatus(userId, id, info.getStatus()); + if (resp == null) { return super.respond(Response.Status.BAD_REQUEST); + } return super.respond(resp); } + /** + * @param uploadId + * @param data + * @return Response with created part data + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry") - public Response createEntry(@PathParam("id") long uploadId, - PartData data, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response createEntry(@PathParam("id") final long uploadId, final PartData data) { try { - String userId = getUserIdFromSessionHeader(sessionId); + final String userId = getUserId(); Logger.info(userId + ": adding entry to upload \"" + uploadId + "\""); - PartData result = creator.createEntry(userId, uploadId, data); + final PartData result = creator.createEntry(userId, uploadId, data); return respond(result); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } + /** + * @param uploadId + * @param entryId + * @param data + * @return Response with updated part data + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry/{entryId}") - public Response updateEntry(@PathParam("id") long uploadId, - @PathParam("entryId") long entryId, - PartData data, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response updateEntry(@PathParam("id") final long uploadId, + @PathParam("entryId") final long entryId, final PartData data) { try { - String userId = getUserIdFromSessionHeader(sessionId); - Logger.info(userId + ": updating entry \"" + entryId + "\" for upload \"" + uploadId + "\""); - PartData result = creator.updateEntry(userId, uploadId, entryId, data); + final String userId = getUserId(); + Logger.info(userId + ": updating entry \"" + entryId + "\" for upload \"" + uploadId + + "\""); + final PartData result = creator.updateEntry(userId, uploadId, entryId, data); return respond(result); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } + /** + * @param info + * @return a bulk upload info object + */ @PUT @Produces(MediaType.APPLICATION_JSON) - public BulkUploadInfo create(BulkUploadInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public BulkUploadInfo create(final BulkUploadInfo info) { + final String userId = getUserId(); Logger.info(userId + ": creating bulk upload draft"); return controller.create(userId, info); } + /** + * @return all bulk uploads for the current user + */ @GET @Produces(MediaType.APPLICATION_JSON) - public ArrayList query(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public ArrayList query() { + final String userId = getUserId(); Logger.info(userId + ": retrieving bulk upload drafts"); return controller.retrieveByUser(userId, userId); } + /** + * @param fileInputStream + * @param type + * @param contentDispositionHeader + * @return Response with the id of the imported bulk upload + */ @POST @Path("file") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response post(@FormDataParam("file") InputStream fileInputStream, - @FormDataParam("type") String type, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response post(@FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("type") final String type, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - String userId = getUserIdFromSessionHeader(sessionId); - String fileName = userId + "-" + contentDispositionHeader.getFileName(); - File file = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + final String userId = getUserId(); + final String fileName = userId + "-" + contentDispositionHeader.getFileName(); + final File file = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), "bulk-import", fileName).toFile(); FileUtils.copyInputStreamToFile(fileInputStream, file); - EntryType addType = EntryType.valueOf(type.toUpperCase()); - FileBulkUpload bulkUpload = new FileBulkUpload(userId, file.toPath(), addType); + final EntryType addType = EntryType.valueOf(type.toUpperCase()); + final FileBulkUpload bulkUpload = new FileBulkUpload(userId, file.toPath(), addType); // converted to string because there is no messagebodywriter for json for long - String importId = Long.toString(bulkUpload.process()); + final String importId = Long.toString(bulkUpload.process()); return Response.status(Response.Status.OK).entity(importId).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()) + .build(); } } @@ -302,10 +376,9 @@ public Response post(@FormDataParam("file") InputStream fileInputStream, @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry/{entryId}") public Response deleteEntry(@PathParam("id") long uploadId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + @PathParam("entryId") long entryId) { try { - String userId = getUserIdFromSessionHeader(sessionId); + final String userId = getUserId(); if (controller.deleteEntry(userId, uploadId, entryId)) return Response.ok().build(); return Response.serverError().build(); @@ -314,34 +387,44 @@ public Response deleteEntry(@PathParam("id") long uploadId, } } + /** + * @param uploadId + * @param entryId + * @return OK response if sequence is deleted + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry/{entryId}/sequence") - public Response deleteEntrySequence(@PathParam("id") long uploadId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response deleteEntrySequence(@PathParam("id") final long uploadId, + @PathParam("entryId") final long entryId) { try { - String userId = getUserIdFromSessionHeader(sessionId); - if (new SequenceController().deleteSequence(userId, entryId)) + final String userId = getUserId(); + if (new SequenceController().deleteSequence(userId, entryId)) { return Response.ok().build(); + } return Response.serverError().build(); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } + /** + * @param uploadId + * @param entryId + * @return OK response if attachment is deleted + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entry/{entryId}/attachment") - public Response deleteEntryAttachment(@PathParam("id") long uploadId, - @PathParam("entryId") long entryId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { + public Response deleteEntryAttachment(@PathParam("id") final long uploadId, + @PathParam("entryId") final long entryId) { try { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.deleteAttachment(userId, uploadId, entryId)) + final String userId = getUserId(); + if (controller.deleteAttachment(userId, uploadId, entryId)) { return Response.ok().build(); + } return Response.serverError().build(); - } catch (Exception e) { + } catch (final Exception e) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); } } diff --git a/src/main/java/org/jbei/ice/services/rest/ConfigResource.java b/src/main/java/org/jbei/ice/services/rest/ConfigResource.java index cd02200a6..ff0595fda 100644 --- a/src/main/java/org/jbei/ice/services/rest/ConfigResource.java +++ b/src/main/java/org/jbei/ice/services/rest/ConfigResource.java @@ -1,16 +1,21 @@ package org.jbei.ice.services.rest; -import org.jbei.ice.lib.config.ConfigurationController; -import org.jbei.ice.lib.dto.Setting; -import org.jbei.ice.lib.dto.search.IndexType; -import org.jbei.ice.lib.search.SearchController; +import java.util.ArrayList; -import javax.ws.rs.*; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; + +import org.jbei.ice.lib.config.ConfigurationController; +import org.jbei.ice.lib.dto.Setting; +import org.jbei.ice.lib.dto.search.IndexType; +import org.jbei.ice.lib.search.SearchController; /** * @author Hector Plahar @@ -24,57 +29,74 @@ public class ConfigResource extends RestResource { /** * Retrieves list of system settings available * - * @param sessionId Session Id for user - * @return list of retrieved system settings that can be changed (including those with no values) + * @return list of retrieved system settings that can be changed (including those with no + * values) */ @GET @Produces(MediaType.APPLICATION_JSON) - public ArrayList get(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public ArrayList get() { + final String userId = getUserId(); return controller.retrieveSystemSettings(userId); } + /** + * @param uriInfo + * @return the version setting of this ICE instance + */ @GET @Path("/version") @Produces(MediaType.APPLICATION_JSON) - public Setting getVersion(@Context UriInfo uriInfo) { - String url = uriInfo.getBaseUri().getAuthority(); + public Setting getVersion(@Context final UriInfo uriInfo) { + final String url = uriInfo.getBaseUri().getAuthority(); return controller.getSystemVersion(url); } /** * Retrieves the value for the specified config key * + * @param key + * config key + * * @return setting containing the passed key and associated value if found */ @GET @Path("/{key}") @Produces(MediaType.APPLICATION_JSON) - public Setting getConfig(@PathParam("key") String key) { + public Setting getConfig(@PathParam("key") final String key) { return controller.getPropertyValue(key); } + /** + * @return Response specifying success or failure of re-index + */ @PUT @Path("/lucene") - public Response buildLuceneIndex(@HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - boolean success = searchController.rebuildIndexes(userId, IndexType.LUCENE); + public Response buildLuceneIndex() { + final String userId = getUserId(); + final boolean success = searchController.rebuildIndexes(userId, IndexType.LUCENE); return super.respond(success); } + /** + * @return Response specifying success or failure of re-index + */ @PUT @Path("/blast") - public Response buildBlastIndex(@HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - boolean success = searchController.rebuildIndexes(userId, IndexType.BLAST); + public Response buildBlastIndex() { + final String userId = getUserId(); + final boolean success = searchController.rebuildIndexes(userId, IndexType.BLAST); return super.respond(success); } + /** + * @param setting + * a config value to update + * @return the updated config key:value + */ @PUT @Produces(MediaType.APPLICATION_JSON) - public Setting update(@HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - Setting setting) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Setting update(final Setting setting) { + final String userId = getUserId(); return controller.updateSetting(userId, setting); } } diff --git a/src/main/java/org/jbei/ice/services/rest/FileResource.java b/src/main/java/org/jbei/ice/services/rest/FileResource.java index b711bdd5a..cd527118b 100644 --- a/src/main/java/org/jbei/ice/services/rest/FileResource.java +++ b/src/main/java/org/jbei/ice/services/rest/FileResource.java @@ -1,11 +1,31 @@ package org.jbei.ice.services.rest; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.file.Paths; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; -import org.jbei.ice.lib.account.SessionHandler; + import org.jbei.ice.lib.bulkupload.FileBulkUpload; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dao.DAOFactory; @@ -27,14 +47,6 @@ import org.jbei.ice.lib.utils.EntriesAsCSV; import org.jbei.ice.lib.utils.Utils; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; -import java.io.*; -import java.net.URI; -import java.nio.file.Paths; - /** * @author Hector Plahar */ @@ -44,25 +56,29 @@ public class FileResource extends RestResource { private SequenceController sequenceController = new SequenceController(); private AttachmentController attachmentController = new AttachmentController(); + /** + * @param fileInputStream + * @param contentDispositionHeader + * @return Response with attachment info on uploaded file + */ @POST @Path("attachment") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response post(@FormDataParam("file") InputStream fileInputStream, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response post(@FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - getUserIdFromSessionHeader(sessionId); - String fileName = contentDispositionHeader.getFileName(); - String fileId = Utils.generateUUID(); - File attachmentFile = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + final String fileName = contentDispositionHeader.getFileName(); + final String fileId = Utils.generateUUID(); + final File attachmentFile = Paths.get( + Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), AttachmentController.attachmentDirName, fileId).toFile(); FileUtils.copyInputStreamToFile(fileInputStream, attachmentFile); - AttachmentInfo info = new AttachmentInfo(); + final AttachmentInfo info = new AttachmentInfo(); info.setFileId(fileId); info.setFilename(fileName); return Response.status(Response.Status.OK).entity(info).build(); - } catch (IOException e) { + } catch (final IOException e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } @@ -70,15 +86,20 @@ public Response post(@FormDataParam("file") InputStream fileInputStream, /** * Retrieves a temp file by fileId + * + * @param fileId + * @return Response with temporary file */ @GET @Path("tmp/{fileId}") - public Response getTmpFile(@PathParam("fileId") String fileId) { - File tmpFile = Paths.get(Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY), fileId).toFile(); - if (tmpFile == null || !tmpFile.exists()) + public Response getTmpFile(@PathParam("fileId") final String fileId) { + final File tmpFile = Paths.get(Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY), + fileId).toFile(); + if (tmpFile == null || !tmpFile.exists()) { return super.respond(Response.Status.NOT_FOUND); + } - Response.ResponseBuilder response = Response.ok(tmpFile); + final Response.ResponseBuilder response = Response.ok(tmpFile); if (tmpFile.getName().endsWith(".csv")) { response.header("Content-Type", "text/csv; name=\"" + tmpFile.getName() + "\""); } @@ -86,207 +107,244 @@ public Response getTmpFile(@PathParam("fileId") String fileId) { return response.build(); } + /** + * @param fileId + * @return Response with attachment + */ @GET @Path("attachment/{fileId}") - public Response getAttachment(@PathParam("fileId") String fileId, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response getAttachment(@PathParam("fileId") final String fileId) { try { - if (StringUtils.isEmpty(sessionId)) - sessionId = sid; - - String userId = getUserIdFromSessionHeader(sessionId); - File file = attachmentController.getAttachmentByFileId(userId, fileId); - if (file == null) + final String userId = getUserId(); + final File file = attachmentController.getAttachmentByFileId(userId, fileId); + if (file == null) { return respond(Response.Status.NOT_FOUND); + } String name = attachmentController.getFileName(userId, fileId); Response.ResponseBuilder response = Response.ok(file); response.header("Content-Disposition", "attachment; filename=\"" + name + "\""); return response.build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } + /** + * @param partnerId + * @param fileId + * @return Response with remote attachment file + */ @GET @Path("remote/{id}/attachment/{fileId}") - public Response getRemoteAttachment(@PathParam("id") long partnerId, - @PathParam("fileId") String fileId, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - RemoteEntries entries = new RemoteEntries(); - File file = entries.getPublicAttachment(userId, partnerId, fileId); - if (file == null) - return respond(Response.Status.NOT_FOUND); + public Response getRemoteAttachment(@PathParam("id") final long partnerId, + @PathParam("fileId") final String fileId) { + try { + final RemoteAccessController controller = new RemoteAccessController(); + final File file = controller.getPublicAttachment(partnerId, fileId); + if (file == null) { + return respond(Response.Status.NOT_FOUND); + } - Response.ResponseBuilder response = Response.ok(file); - response.header("Content-Disposition", "attachment; filename=\"remoteAttachment\""); - return response.build(); + final Response.ResponseBuilder response = Response.ok(file); + response.header("Content-Disposition", "attachment; filename=\"remoteAttachment\""); + return response.build(); + } catch (final Exception e) { + Logger.error(e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } } + /** + * @param type + * @param linkedType + * @return Response with upload CSV file + */ @GET @Path("upload/{type}") - public Response getUploadCSV(@PathParam("type") String type, @QueryParam("link") String linkedType) { + public Response getUploadCSV(@PathParam("type") final String type, + @QueryParam("link") final String linkedType) { final EntryType entryAddType = EntryType.nameToType(type); final EntryType linked; - if (linkedType != null) + if (linkedType != null) { linked = EntryType.nameToType(linkedType); - else + } else { linked = null; + } - StreamingOutput stream = new StreamingOutput() { + final StreamingOutput stream = new StreamingOutput() { @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - byte[] template = FileBulkUpload.getCSVTemplateBytes(entryAddType, linked); - ByteArrayInputStream stream = new ByteArrayInputStream(template); + public void write(final OutputStream output) throws IOException, + WebApplicationException { + final byte[] template = FileBulkUpload.getCSVTemplateBytes(entryAddType, linked); + final ByteArrayInputStream stream = new ByteArrayInputStream(template); IOUtils.copy(stream, output); } }; String filename = type.toLowerCase(); - if (linkedType != null) + if (linkedType != null) { filename += ("_" + linkedType.toLowerCase()); + } - return Response.ok(stream).header("Content-Disposition", "attachment;filename=" - + filename + "_csv_upload.csv").build(); + return Response + .ok(stream) + .header("Content-Disposition", + "attachment;filename=" + filename + "_csv_upload.csv").build(); } + /** + * @param partId + * @param downloadType + * @return Response with sequence file + */ @GET @Path("{partId}/sequence/{type}") - public Response downloadSequence( - @PathParam("partId") final long partId, - @PathParam("type") final String downloadType, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { - if (StringUtils.isEmpty(sessionId)) - sessionId = sid; - - final String userId = getUserIdFromSessionHeader(sessionId); - final ByteArrayWrapper wrapper = sequenceController.getSequenceFile(userId, partId, downloadType); + public Response downloadSequence(@PathParam("partId") final long partId, + @PathParam("type") final String downloadType) { + final String userId = getUserId(); + final ByteArrayWrapper wrapper = sequenceController.getSequenceFile(userId, partId, + downloadType); - StreamingOutput stream = new StreamingOutput() { + final StreamingOutput stream = new StreamingOutput() { @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - ByteArrayInputStream stream = new ByteArrayInputStream(wrapper.getBytes()); + public void write(final OutputStream output) throws IOException, + WebApplicationException { + final ByteArrayInputStream stream = new ByteArrayInputStream(wrapper.getBytes()); IOUtils.copy(stream, output); } }; - return Response.ok(stream).header("Content-Disposition", "attachment;filename=" + wrapper.getName()).build(); + return Response.ok(stream) + .header("Content-Disposition", "attachment;filename=" + wrapper.getName()).build(); } + /** + * @param fileId + * @return Response with sequence file + */ @GET @Path("trace/{fileId}") - public Response getTraceSequenceFile(@PathParam("fileId") String fileId, - @QueryParam("sid") String sid, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response getTraceSequenceFile(@PathParam("fileId") final String fileId) { try { - SequenceAnalysisController sequenceAnalysisController = new SequenceAnalysisController(); - TraceSequence traceSequence = sequenceAnalysisController.getTraceSequenceByFileId(fileId); + final SequenceAnalysisController sequenceAnalysisController = new SequenceAnalysisController(); + final TraceSequence traceSequence = sequenceAnalysisController + .getTraceSequenceByFileId(fileId); if (traceSequence != null) { - File file = sequenceAnalysisController.getFile(traceSequence); - Response.ResponseBuilder response = Response.ok(file); - response.header("Content-Disposition", "attachment; filename=\"" + traceSequence.getFilename() + "\""); + final File file = sequenceAnalysisController.getFile(traceSequence); + final Response.ResponseBuilder response = Response.ok(file); + response.header("Content-Disposition", + "attachment; filename=\"" + traceSequence.getFilename() + "\""); return response.build(); } return Response.serverError().build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.serverError().build(); } } + /** + * @param recordId + * @return Response with image file for the SBOL + */ @GET @Produces("image/png") @Path("sbolVisual/{rid}") - public Response getSBOLVisual(@PathParam("rid") String recordId, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response getSBOLVisual(@PathParam("rid") final String recordId) { try { - String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); - Entry entry = DAOFactory.getEntryDAO().getByRecordId(recordId); - Sequence sequence = entry.getSequence(); - String hash = sequence.getFwdHash(); - String fileId; - - if (Paths.get(tmpDir, hash + ".png").toFile().exists()) { - fileId = (hash + ".png"); - File file = Paths.get(tmpDir, fileId).toFile(); + final String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); + final Entry entry = DAOFactory.getEntryDAO().getByRecordId(recordId); + final Sequence sequence = entry.getSequence(); + final String hash = sequence.getFwdHash(); + final File png = Paths.get(tmpDir, hash + ".png").toFile(); - Response.ResponseBuilder response = Response.ok(file); - response.header("Content-Disposition", "attachment; filename=" + entry.getPartNumber() + ".png"); + if (png.exists()) { + final Response.ResponseBuilder response = Response.ok(png); + response.header("Content-Disposition", + "attachment; filename=" + entry.getPartNumber() + ".png"); return response.build(); - } else { - URI uri = PigeonSBOLv.generatePigeonVisual(sequence); - if (uri != null) { - IOUtils.copy(uri.toURL().openStream(), - new FileOutputStream(tmpDir + File.separatorChar + hash + ".png")); - fileId = (hash + ".png"); - File file = Paths.get(tmpDir, fileId).toFile(); - - Response.ResponseBuilder response = Response.ok(file); - response.header("Content-Disposition", "attachment; filename=" + entry.getPartNumber() + ".png"); - return response.build(); + } + final URI uri = PigeonSBOLv.generatePigeonVisual(sequence); + if (uri != null) { + try (final InputStream in = uri.toURL().openStream(); + final OutputStream out = new FileOutputStream(png);) { + IOUtils.copy(in, out); } + final Response.ResponseBuilder response = Response.ok(png); + response.header("Content-Disposition", + "attachment; filename=" + entry.getPartNumber() + ".png"); + return response.build(); } - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return null; } return null; } - // this creates an entry if an id is not specified in the form data + /** + * this creates an entry if an id is not specified in the form data + * + * @param fileInputStream + * @param recordId + * @param entryType + * @param contentDispositionHeader + * @return Response containing sequence info + */ @POST @Path("sequence") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) - public Response uploadSequence(@FormDataParam("file") InputStream fileInputStream, - @FormDataParam("entryRecordId") String recordId, - @FormDataParam("entryType") String entryType, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { + public Response uploadSequence(@FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("entryRecordId") final String recordId, + @FormDataParam("entryType") final String entryType, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader) { try { - if (entryType == null) + if (entryType == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } - String fileName = contentDispositionHeader.getFileName(); - String userId = SessionHandler.getUserIdBySession(sessionId); - String sequence = IOUtils.toString(fileInputStream); - SequenceInfo sequenceInfo = sequenceController.parseSequence(userId, recordId, entryType, sequence, - fileName); - if (sequenceInfo == null) + final String fileName = contentDispositionHeader.getFileName(); + final String userId = getUserId(); + final String sequence = IOUtils.toString(fileInputStream); + final SequenceInfo sequenceInfo = sequenceController.parseSequence(userId, recordId, + entryType, sequence, fileName); + if (sequenceInfo == null) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } return Response.status(Response.Status.OK).entity(sequenceInfo).build(); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } /** - * Extracts the csv information and writes it to the temp dir and returns the file uuid. - * Then the client is expected to make another rest call with the uuid is a separate window. - * This workaround is due to not being able to download files using XHR or sumsuch + * Extracts the csv information and writes it to the temp dir and returns the file uuid. Then + * the client is expected to make another rest call with the uuid is a separate window. This + * workaround is due to not being able to download files using XHR or sumsuch + * + * @param selection + * @return Response with filename wrapped in a Setting object */ @POST @Path("csv") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response downloadCSV( - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId, - EntrySelection selection) { - String userId = super.getUserIdFromSessionHeader(sessionId); - EntriesAsCSV entriesAsCSV = new EntriesAsCSV(); - boolean success = entriesAsCSV.setSelectedEntries(userId, selection); - if (!success) + public Response downloadCSV(final EntrySelection selection) { + final String userId = getUserId(); + final EntriesAsCSV entriesAsCSV = new EntriesAsCSV(); + final boolean success = entriesAsCSV.setSelectedEntries(userId, selection); + if (!success) { return super.respond(false); + } - File file = entriesAsCSV.getFilePath().toFile(); - if (file.exists()) + final File file = entriesAsCSV.getFilePath().toFile(); + if (file.exists()) { return Response.ok(new Setting("key", file.getName())).build(); + } return respond(false); } } diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index feaa4b0c3..5e28a7858 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -64,7 +64,7 @@ public Key getKey(final String keyId) { private static final HmacAuthorizor AUTHORIZOR = new HmacAuthorizor(TABLE); - @HeaderParam(value = "X-ICE-Authentication-SessionId") + @HeaderParam(value = AUTHENTICATION_PARAM_NAME) private String sessionId; @HeaderParam(value = "Authorization") From 98368db6b294dc4fd13b9817932a612488832516 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 2 Apr 2015 17:44:16 -0700 Subject: [PATCH 22/67] Converting more resources; PartResource sometimes needs to authenticate via query parameter, added support to RestResource to handle these cases --- .../ice/services/rest/FolderResource.java | 326 ++++++---- .../jbei/ice/services/rest/GroupResource.java | 37 +- .../ice/services/rest/MessageResource.java | 14 +- .../jbei/ice/services/rest/PartResource.java | 556 +++++++++++------- .../jbei/ice/services/rest/RestResource.java | 27 + 5 files changed, 611 insertions(+), 349 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/FolderResource.java b/src/main/java/org/jbei/ice/services/rest/FolderResource.java index 51d6417d7..f55559c0b 100644 --- a/src/main/java/org/jbei/ice/services/rest/FolderResource.java +++ b/src/main/java/org/jbei/ice/services/rest/FolderResource.java @@ -1,7 +1,24 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.jbei.ice.lib.access.PermissionsController; -import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.entry.PartData; import org.jbei.ice.lib.dto.folder.FolderDetails; @@ -12,14 +29,6 @@ import org.jbei.ice.lib.folder.*; import org.jbei.ice.lib.shared.ColumnField; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; -import java.util.List; - /** * @author Hector Plahar */ @@ -30,123 +39,154 @@ public class FolderResource extends RestResource { private FolderContentRetriever retriever = new FolderContentRetriever(); private PermissionsController permissionsController = new PermissionsController(); + /** + * @return all collections visible to current user + */ @GET @Produces(MediaType.APPLICATION_JSON) - public Collection retrieveCollection( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String sid = getUserIdFromSessionHeader(userAgentHeader); + public Collection retrieveCollection() { + final String sid = getUserId(); return controller.getFolderStats(sid); } + /** + * @param folder + * @return Response with info on created folder + */ @PUT @Produces(MediaType.APPLICATION_JSON) - public FolderDetails create( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - FolderDetails folder) { - String sid = getUserIdFromSessionHeader(userAgentHeader); + public FolderDetails create(final FolderDetails folder) { + final String sid = getUserId(); return controller.createPersonalFolder(sid, folder); } - // TODO : allow api key as well + /** + * TODO allow api key as well + * + * @return all public collections + */ @GET @Path("/public") @Produces(MediaType.APPLICATION_JSON) - public ArrayList getPublicFolders( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public ArrayList getPublicFolders() { return controller.getPublicFolders(); } + /** + * @param folderType + * @return all collections of a type + */ @GET @Path("/{type}") @Produces(MediaType.APPLICATION_JSON) public ArrayList getSubFolders( @DefaultValue("personal") @PathParam("type") String folderType, - @DefaultValue("false") @QueryParam("canEdit") boolean canEdit, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String sid = getUserIdFromSessionHeader(userAgentHeader); + @DefaultValue("false") @QueryParam("canEdit") boolean canEdit) { + final String sid = getUserId(); if (canEdit) return new Folders().getCanEditFolders(sid); switch (folderType) { - case "personal": - return controller.getUserFolders(sid); + case "personal": + return controller.getUserFolders(sid); - case "available": - return controller.getAvailableFolders(sid); + case "available": + return controller.getAvailableFolders(sid); - case "drafts": - return controller.getBulkUploadDrafts(sid); + case "drafts": + return controller.getBulkUploadDrafts(sid); - case "pending": - return controller.getPendingBulkUploads(sid); + case "pending": + return controller.getPendingBulkUploads(sid); - case "shared": - return controller.getSharedUserFolders(sid); + case "shared": + return controller.getSharedUserFolders(sid); - default: - return new ArrayList<>(); + default: + return new ArrayList<>(); } } + /** + * @param folderId + * @param details + * @return Response with updated collection info + */ @PUT @Path("/{id}") - public Response update(@PathParam("id") long folderId, - FolderDetails details, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - FolderDetails resp = controller.update(userId, folderId, details); + public Response update(@PathParam("id") final long folderId, final FolderDetails details) { + final String userId = getUserId(); + final FolderDetails resp = controller.update(userId, folderId, details); return super.respond(Response.Status.OK, resp); } + /** + * @param folderId + * @param folderType + * @return the details of the deleted collection + */ @DELETE @Path("/{id}") - public FolderDetails deleteFolder(@PathParam("id") long folderId, - @QueryParam("type") String folderType, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - FolderType type = FolderType.valueOf(folderType); + public FolderDetails deleteFolder(@PathParam("id") final long folderId, + @QueryParam("type") final String folderType) { + final String userId = getUserId(); + final FolderType type = FolderType.valueOf(folderType); return controller.delete(userId, folderId, type); } + /** + * @param entrySelection + * @return Response with updated collection details + */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/transfer") - public Response addSelectedEntriesToFolder( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - EntrySelection entrySelection) { - String userId = getUserIdFromSessionHeader(sessionId); - FolderContent folderContent = new FolderContent(); - List result = folderContent.addEntrySelection(userId, entrySelection); + public Response addSelectedEntriesToFolder(final EntrySelection entrySelection) { + final String userId = getUserId(); + final FolderContent folderContent = new FolderContent(); + final List result = folderContent.addEntrySelection(userId, entrySelection); return super.respond(result); } + /** + * @param entrySelection + * @param folderId + * @return Response indicating success or failure + */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") - public Response removeEntriesFromFolder( - EntrySelection entrySelection, - @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.removeFolderContents(userId, folderId, entrySelection)) + public Response removeEntriesFromFolder(final EntrySelection entrySelection, + @PathParam("id") final long folderId) { + final String userId = getUserId(); + if (controller.removeFolderContents(userId, folderId, entrySelection)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param uriInfo + * @param folderId + * @param offset + * @param limit + * @param sort + * @param asc + * @return details of the selected collection + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") - public FolderDetails read(@Context UriInfo uriInfo, - @PathParam("id") String folderId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public FolderDetails read(@Context final UriInfo uriInfo, + @PathParam("id") final String folderId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { - ColumnField field = ColumnField.valueOf(sort.toUpperCase()); + final ColumnField field = ColumnField.valueOf(sort.toUpperCase()); if (folderId.equalsIgnoreCase("public")) { // return public entries @@ -154,118 +194,148 @@ public FolderDetails read(@Context UriInfo uriInfo, return controller.getPublicEntries(field, offset, limit, asc); } - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + final String userId = getUserId(); try { - long id = Long.decode(folderId); + final long id = Long.decode(folderId); Logger.info("Retrieving folder " + id + " entries"); return controller.retrieveFolderContents(userId, id, field, asc, offset, limit); - } catch (NumberFormatException nfe) { + } catch (final NumberFormatException nfe) { } - EntryController entryController = new EntryController(); - FolderDetails details = new FolderDetails(); + final EntryController entryController = new EntryController(); + final FolderDetails details = new FolderDetails(); log(userId, "retrieving " + folderId + " entries"); switch (folderId) { - case "personal": - List entries = entryController.retrieveOwnerEntries(userId, userId, field, - asc, offset, limit); - long count = entryController.getNumberOfOwnerEntries(userId, userId); - details.getEntries().addAll(entries); - details.setCount(count); - return details; - - case "available": - FolderDetails retrieved = entryController.retrieveVisibleEntries(userId, field, asc, offset, limit); - details.setEntries(retrieved.getEntries()); - details.setCount(entryController.getNumberOfVisibleEntries(userId)); - return details; - - case "shared": - List data = entryController.getEntriesSharedWithUser(userId, field, asc, offset, limit); - details.setEntries(data); - details.setCount(entryController.getNumberOfEntriesSharedWithUser(userId)); - return details; - - case "drafts": - return retriever.getDraftEntries(userId, field, asc, offset, limit); - - case "deleted": - return retriever.getDeletedEntries(userId, field, asc, offset, limit); - - case "pending": - return retriever.getPendingEntries(userId, field, asc, offset, limit); - - case "transferred": - return retriever.getTransferredEntries(userId, field, asc, offset, limit); - - default: - return null; + case "personal": + final List entries = entryController.retrieveOwnerEntries(userId, userId, + field, asc, offset, limit); + final long count = entryController.getNumberOfOwnerEntries(userId, userId); + details.getEntries().addAll(entries); + details.setCount(count); + return details; + + case "available": + final FolderDetails retrieved = entryController.retrieveVisibleEntries(userId, field, + asc, offset, limit); + details.setEntries(retrieved.getEntries()); + details.setCount(entryController.getNumberOfVisibleEntries(userId)); + return details; + + case "shared": + final List data = entryController.getEntriesSharedWithUser(userId, field, + asc, offset, limit); + details.setEntries(data); + details.setCount(entryController.getNumberOfEntriesSharedWithUser(userId)); + return details; + + case "drafts": + return retriever.getDraftEntries(userId, field, asc, offset, limit); + + case "deleted": + return retriever.getDeletedEntries(userId, field, asc, offset, limit); + + case "pending": + return retriever.getPendingEntries(userId, field, asc, offset, limit); + + case "transferred": + return retriever.getTransferredEntries(userId, field, asc, offset, limit); + + default: + return null; } } + /** + * @param folderId + * @return Response with permissions on a collection + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public Response getFolderPermissions( - @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response getFolderPermissions(@PathParam("id") final long folderId) { + final String userId = getUserId(); return respond(controller.getPermissions(userId, folderId)); } + /** + * @param info + * @param folderId + * @param permissions + * @return details of the modified collection + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public FolderDetails setPermissions(@Context UriInfo info, @PathParam("id") long folderId, - ArrayList permissions, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public FolderDetails setPermissions(@Context final UriInfo info, + @PathParam("id") final long folderId, final ArrayList permissions) { + final String userId = getUserId(); return permissionsController.setFolderPermissions(userId, folderId, permissions); } + /** + * @param info + * @param folderId + * @param permission + * @return the added permission + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public AccessPermission addPermission(@Context UriInfo info, @PathParam("id") long folderId, - AccessPermission permission, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public AccessPermission addPermission(@Context final UriInfo info, + @PathParam("id") final long folderId, final AccessPermission permission) { + final String userId = getUserId(); return controller.createFolderPermission(userId, folderId, permission); } + /** + * @param info + * @param partId + * @param permissionId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/{permissionId}") - public Response removePermission(@Context UriInfo info, - @PathParam("id") long partId, - @PathParam("permissionId") long permissionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response removePermission(@Context final UriInfo info, + @PathParam("id") final long partId, @PathParam("permissionId") final long permissionId) { + final String userId = getUserId(); permissionsController.removeFolderPermission(userId, partId, permissionId); return Response.ok().build(); } + /** + * @param info + * @param folderId + * @return Response for success or failure + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response enablePublicAccess(@Context UriInfo info, @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (controller.enablePublicReadAccess(userId, folderId)) + public Response enablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long folderId) { + final String userId = getUserId(); + if (controller.enablePublicReadAccess(userId, folderId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param info + * @param folderId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response disablePublicAccess(@Context UriInfo info, @PathParam("id") long folderId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (controller.disablePublicReadAccess(userId, folderId)) + public Response disablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long folderId) { + final String userId = getUserId(); + if (controller.disablePublicReadAccess(userId, folderId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } } diff --git a/src/main/java/org/jbei/ice/services/rest/GroupResource.java b/src/main/java/org/jbei/ice/services/rest/GroupResource.java index 854fde4be..e8df5afdb 100644 --- a/src/main/java/org/jbei/ice/services/rest/GroupResource.java +++ b/src/main/java/org/jbei/ice/services/rest/GroupResource.java @@ -1,8 +1,8 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; + import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -22,34 +22,43 @@ public class GroupResource extends RestResource { private GroupController groupController = new GroupController(); + /** + * @param id + * @return Response with group info + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public Response getGroup(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - UserGroup group = groupController.getGroupById(userId, id); + public Response getGroup(@PathParam("id") final long id) { + final String userId = getUserId(); + final UserGroup group = groupController.getGroupById(userId, id); return respond(group); } + /** + * @param id + * @return Response with group members + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/members") - public Response getGroupMembers(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - ArrayList members = groupController.getGroupMembers(userId, id); + public Response getGroupMembers(@PathParam("id") final long id) { + final String userId = getUserId(); + final ArrayList members = groupController.getGroupMembers(userId, id); return respond(members); } + /** + * @param id + * @param group + * @return response with success or failure + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public Response updateGroup(@PathParam("id") long id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - UserGroup group) { - String userId = getUserIdFromSessionHeader(sessionId); - boolean success = groupController.updateGroup(userId, group); + public Response updateGroup(@PathParam("id") final long id, final UserGroup group) { + final String userId = getUserId(); + final boolean success = groupController.updateGroup(userId, group); return respond(success); } } diff --git a/src/main/java/org/jbei/ice/services/rest/MessageResource.java b/src/main/java/org/jbei/ice/services/rest/MessageResource.java index 2e5546d02..b069882d0 100644 --- a/src/main/java/org/jbei/ice/services/rest/MessageResource.java +++ b/src/main/java/org/jbei/ice/services/rest/MessageResource.java @@ -2,7 +2,6 @@ import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; @@ -20,13 +19,16 @@ public class MessageResource extends RestResource { private MessageController controller = new MessageController(); + /** + * @param offset + * @param limit + * @return list of messages + */ @GET @Produces(MediaType.APPLICATION_JSON) - public MessageList get( - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public MessageList get(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit) { + final String userId = getUserId(); Logger.info(userId + ": retrieving available messages"); return controller.retrieveMessages(userId, userId, offset, limit); } diff --git a/src/main/java/org/jbei/ice/services/rest/PartResource.java b/src/main/java/org/jbei/ice/services/rest/PartResource.java index ba52dbb0b..7bfd27087 100644 --- a/src/main/java/org/jbei/ice/services/rest/PartResource.java +++ b/src/main/java/org/jbei/ice/services/rest/PartResource.java @@ -1,20 +1,48 @@ package org.jbei.ice.services.rest; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + import org.jbei.ice.lib.access.PermissionException; import org.jbei.ice.lib.access.PermissionsController; -import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.ConfigurationKey; import org.jbei.ice.lib.dto.History; import org.jbei.ice.lib.dto.comment.UserComment; -import org.jbei.ice.lib.dto.entry.*; +import org.jbei.ice.lib.dto.entry.AttachmentInfo; +import org.jbei.ice.lib.dto.entry.AutoCompleteField; +import org.jbei.ice.lib.dto.entry.EntryType; +import org.jbei.ice.lib.dto.entry.PartData; +import org.jbei.ice.lib.dto.entry.PartStatistics; +import org.jbei.ice.lib.dto.entry.TraceSequenceAnalysis; import org.jbei.ice.lib.dto.permission.AccessPermission; import org.jbei.ice.lib.dto.sample.PartSample; import org.jbei.ice.lib.entry.Entries; @@ -30,20 +58,6 @@ import org.jbei.ice.lib.utils.Utils; import org.jbei.ice.lib.vo.FeaturedDNASequence; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Type; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - /** * @author Hector Plahar */ @@ -58,6 +72,12 @@ public class PartResource extends RestResource { private ExperimentController experimentController = new ExperimentController(); private SampleController sampleController = new SampleController(); + /** + * @param val + * @param field + * @param limit + * @return list of autocomplete values for a field + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") @@ -69,6 +89,11 @@ public ArrayList autoComplete(@QueryParam("val") String val, return new ArrayList<>(result); } + /** + * @param token + * @param limit + * @return list of autocomplete values for parts + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete/partid") @@ -78,369 +103,488 @@ public ArrayList autoComplete(@QueryParam("token") String token, } /** - * Retrieves a part using any of the unique identifiers. e.g. Part number, synthetic id, or global unique - * identifier + * Retrieves a part using any of the unique identifiers. e.g. Part number, synthetic id, or + * global unique identifier + * + * @param info + * @param id + * @return Response with part data */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public Response read(@Context UriInfo info, - @PathParam("id") String id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = SessionHandler.getUserIdBySession(sessionId); + public Response read(@Context final UriInfo info, @PathParam("id") final String id) { + final String userId = getUserId(); try { log(userId, "retrieving details for " + id); - EntryType type = EntryType.nameToType(id); + final EntryType type = EntryType.nameToType(id); PartData data; - if (type != null) + if (type != null) { data = controller.getPartDefaults(userId, type); - else + } else { data = controller.retrieveEntryDetails(userId, id); + } return super.respond(data); - } catch (PermissionException pe) { + } catch (final PermissionException pe) { // todo : have a generic error entity returned return Response.status(Response.Status.FORBIDDEN).build(); } } + /** + * @param id + * @return part data with tooltip information + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/tooltip") - public PartData getTooltipDetails(@PathParam("id") String id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public PartData getTooltipDetails(@PathParam("id") final String id) { + final String userId = getUserId(); return controller.retrieveEntryTipDetails(userId, id); } + /** + * @param info + * @param id + * @return permissions on the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public ArrayList getPermissions(@Context UriInfo info, @PathParam("id") String id, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public List getPermissions(@Context final UriInfo info, + @PathParam("id") final String id) { + final String userId = getUserId(); return retriever.getEntryPermissions(userId, id); } + /** + * @param info + * @param partId + * @param permissions + * @return part data with permission information + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public PartData setPermissions(@Context UriInfo info, @PathParam("id") long partId, - ArrayList permissions, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public PartData setPermissions(@Context final UriInfo info, @PathParam("id") final long partId, + final ArrayList permissions) { + final String userId = getUserId(); return permissionsController.setEntryPermissions(userId, partId, permissions); } + /** + * @param partId + * @return Response with studies on a part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/experiments") - public Response getPartExperiments(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - ArrayList studies = experimentController.getPartStudies(userId, partId); - if (studies == null) + public Response getPartExperiments(@PathParam("id") final long partId) { + final String userId = getUserId(); + final List studies = experimentController.getPartStudies(userId, partId); + if (studies == null) { return respond(Response.Status.INTERNAL_SERVER_ERROR); + } return respond(Response.Status.OK, studies); } + /** + * @param partId + * @param study + * @return response with study information + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/experiments") - public Response getPartExperiments(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - Study study) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - study = experimentController.createStudy(userId, partId, study); - return respond(Response.Status.OK, study); + public Response getPartExperiments(@PathParam("id") final long partId, final Study study) { + final String userId = getUserId(); + final Study created = experimentController.createStudy(userId, partId, study); + return respond(Response.Status.OK, created); } + /** + * @param info + * @param partId + * @return Response for success or failure + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response enablePublicAccess(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (permissionsController.enablePublicReadAccess(userId, partId)) + public Response enablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); + if (permissionsController.enablePublicReadAccess(userId, partId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param info + * @param partId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/public") - public Response disablePublicAccess(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (permissionsController.disablePublicReadAccess(userId, partId)) + public Response disablePublicAccess(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); + if (permissionsController.disablePublicReadAccess(userId, partId)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param info + * @param partId + * @param permission + * @return the created permission + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions") - public AccessPermission createPermission(@Context UriInfo info, @PathParam("id") long partId, - AccessPermission permission, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public AccessPermission createPermission(@Context final UriInfo info, + @PathParam("id") final long partId, final AccessPermission permission) { + final String userId = getUserId(); return permissionsController.createPermission(userId, partId, permission); } + /** + * @param info + * @param partId + * @param permissionId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/permissions/{permissionId}") - public Response removePermission(@Context UriInfo info, - @PathParam("id") long partId, - @PathParam("permissionId") long permissionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response removePermission(@Context final UriInfo info, + @PathParam("id") final long partId, @PathParam("permissionId") final long permissionId) { + final String userId = getUserId(); permissionsController.removeEntryPermission(userId, partId, permissionId); return Response.ok().build(); } + /** + * @param partId + * @return statistics on part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/statistics") - public PartStatistics getStatistics(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public PartStatistics getStatistics(@PathParam("id") final long partId) { + final String userId = getUserId(); return controller.retrieveEntryStatistics(userId, partId); } + /** + * @param info + * @param partId + * @return comments on part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/comments") - public ArrayList getComments(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public List getComments(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); return controller.retrieveEntryComments(userId, partId); } + /** + * @param partId + * @param userComment + * @return the created comment + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/comments") - public Response createComment(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - UserComment userComment) { -// if(userComment == null || userComment.getMessage() == null) -// throw new Web + public Response createComment(@PathParam("id") final long partId, final UserComment userComment) { // todo : check for null - String userId = getUserIdFromSessionHeader(userAgentHeader); + final String userId = getUserId(); log(userId, "adding comment to entry " + partId); - UserComment comment = controller.createEntryComment(userId, partId, userComment); + final UserComment comment = controller.createEntryComment(userId, partId, userComment); return respond(comment); } + /** + * @param partId + * @param commentId + * @param userComment + * @return the updated comment + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/comments/{commentId}") - public UserComment updateComment(@PathParam("id") long partId, - @PathParam("commentId") long commentId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - UserComment userComment) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public UserComment updateComment(@PathParam("id") final long partId, + @PathParam("commentId") final long commentId, final UserComment userComment) { + final String userId = getUserId(); return controller.updateEntryComment(userId, partId, commentId, userComment); } + /** + * @param partId + * @param attachment + * @return created attachment info + */ @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Path("/{id}/attachments") - public AttachmentInfo addAttachment(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - AttachmentInfo attachment) { + public AttachmentInfo addAttachment(@PathParam("id") final long partId, + final AttachmentInfo attachment) { // todo : check for null - String userId = getUserIdFromSessionHeader(userAgentHeader); - AttachmentController attachmentController = new AttachmentController(); + final String userId = getUserId(); + final AttachmentController attachmentController = new AttachmentController(); return attachmentController.addAttachmentToEntry(userId, partId, attachment); } + /** + * @param partId + * @return all attachments on a part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/attachments") - public ArrayList getAttachments(@PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public List getAttachments(@PathParam("id") final long partId) { + final String userId = getUserId(); return attachmentController.getByEntry(userId, partId); } + /** + * @param info + * @param partId + * @param attachmentId + * @return A response for success or failure + */ @DELETE @Path("/{id}/attachments/{attachmentId}") - public Response deleteAttachment(@Context UriInfo info, - @PathParam("id") long partId, - @PathParam("attachmentId") long attachmentId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (!attachmentController.delete(userId, partId, attachmentId)) + public Response deleteAttachment(@Context final UriInfo info, + @PathParam("id") final long partId, @PathParam("attachmentId") final long attachmentId) { + final String userId = getUserId(); + if (!attachmentController.delete(userId, partId, attachmentId)) { return Response.notModified().build(); // todo : use 404 ? + } return Response.ok().build(); } + /** + * @param info + * @param partId + * @param sessionId + * @return history entries for the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/history") - public ArrayList getHistory(@Context UriInfo info, - @PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - String userId = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList getHistory(@Context final UriInfo info, + @PathParam("id") final long partId, @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); return controller.getHistory(userId, partId); } + /** + * @param partId + * @param historyId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/history/{historyId}") - public Response delete(@PathParam("id") long partId, - @PathParam("historyId") long historyId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - boolean success = controller.deleteHistory(userId, partId, historyId); + public Response delete(@PathParam("id") final long partId, + @PathParam("historyId") final long historyId) { + final String userId = getUserId(); + final boolean success = controller.deleteHistory(userId, partId, historyId); return super.respond(success); } + /** + * @param info + * @param partId + * @param sessionId + * @return traces for the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/traces") - public ArrayList getTraces(@Context UriInfo info, - @PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public ArrayList getTraces(@Context final UriInfo info, + @PathParam("id") final long partId, @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); return controller.getTraceSequences(userId, partId); } + /** + * @param partId + * @param fileInputStream + * @param contentDispositionHeader + * @param sessionId + * @return Response for success or failure + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/traces") - public Response addTraceSequence(@PathParam("id") long partId, - @FormDataParam("file") InputStream fileInputStream, - @FormDataParam("file") FormDataContentDisposition contentDispositionHeader, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - String userId = getUserIdFromSessionHeader(userAgentHeader); - String fileName = contentDispositionHeader.getFileName(); - String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); - File file = Paths.get(tmpDir, fileName).toFile(); + public Response addTraceSequence(@PathParam("id") final long partId, + @FormDataParam("file") final InputStream fileInputStream, + @FormDataParam("file") final FormDataContentDisposition contentDispositionHeader, + @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); + final String fileName = contentDispositionHeader.getFileName(); + final String tmpDir = Utils.getConfigValue(ConfigurationKey.TEMPORARY_DIRECTORY); + final File file = Paths.get(tmpDir, fileName).toFile(); try { FileUtils.copyInputStreamToFile(fileInputStream, file); - } catch (IOException e) { + } catch (final IOException e) { Logger.error(e); return respond(Response.Status.INTERNAL_SERVER_ERROR); } - boolean success = controller.addTraceSequence(userId, partId, file, fileName); + final boolean success = controller.addTraceSequence(userId, partId, file, fileName); return respond(success); } + /** + * @param info + * @param partId + * @param traceId + * @return Response for success or failure + */ @DELETE @Path("/{id}/traces/{traceId}") - public Response deleteTrace(@Context UriInfo info, @PathParam("id") long partId, - @PathParam("traceId") long traceId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - if (!controller.deleteTraceSequence(userId, partId, traceId)) + public Response deleteTrace(@Context final UriInfo info, @PathParam("id") final long partId, + @PathParam("traceId") final long traceId) { + final String userId = getUserId(); + if (!controller.deleteTraceSequence(userId, partId, traceId)) { return super.respond(Response.Status.UNAUTHORIZED); + } return super.respond(Response.Status.OK); } + /** + * @param info + * @param partId + * @return samples on the part + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples") - public ArrayList getSamples(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public List getSamples(@Context final UriInfo info, + @PathParam("id") final long partId) { + final String userId = getUserId(); return sampleController.retrieveEntrySamples(userId, partId); } + /** + * @param info + * @param partId + * @param strainNamePrefix + * @param partSample + * @return all samples on a part + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples") - public ArrayList addSample(@Context UriInfo info, @PathParam("id") long partId, - @QueryParam("strainNamePrefix") String strainNamePrefix, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - PartSample partSample) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); + public List addSample(@Context final UriInfo info, + @PathParam("id") final long partId, + @QueryParam("strainNamePrefix") final String strainNamePrefix, + final PartSample partSample) { + final String userId = getUserId(); log(userId, "creating sample for part " + partId); sampleController.createSample(userId, partId, partSample, strainNamePrefix); return sampleController.retrieveEntrySamples(userId, partId); } + /** + * @param info + * @param partId + * @param sampleId + * @return Response for success or failure + */ @DELETE @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples/{sampleId}") - public Response deleteSample(@Context UriInfo info, @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @PathParam("sampleId") long sampleId) { - String userId = SessionHandler.getUserIdBySession(userAgentHeader); - boolean success = sampleController.delete(userId, partId, sampleId); + public Response deleteSample(@Context final UriInfo info, @PathParam("id") final long partId, + @PathParam("sampleId") final long sampleId) { + final String userId = getUserId(); + final boolean success = sampleController.delete(userId, partId, sampleId); return super.respond(success); } + /** + * @param partId + * @param sessionId + * @return Response with the part sequence + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/sequence") - public Response getSequence(@PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - - String userId = SessionHandler.getUserIdBySession(userAgentHeader); - FeaturedDNASequence sequence = sequenceController.retrievePartSequence(userId, partId); - if (sequence == null) + public Response getSequence(@PathParam("id") final long partId, + @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); + final FeaturedDNASequence sequence = sequenceController.retrievePartSequence(userId, partId); + if (sequence == null) { return Response.status(Response.Status.NO_CONTENT).build(); + } return Response.status(Response.Status.OK).entity(sequence).build(); } + /** + * @param partId + * @param sessionId + * @param sequence + * @return the updated sequence + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/sequence") - public FeaturedDNASequence updateSequence(@PathParam("id") long partId, - @QueryParam("sid") String sessionId, - FeaturedDNASequence sequence, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - if (StringUtils.isEmpty(userAgentHeader)) - userAgentHeader = sessionId; - - String userId = getUserIdFromSessionHeader(userAgentHeader); + public FeaturedDNASequence updateSequence(@PathParam("id") final long partId, + @QueryParam("sid") final String sessionId, final FeaturedDNASequence sequence) { + final String userId = getUserId(sessionId); return sequenceController.updateSequence(userId, partId, sequence); } + /** + * @param partId + * @param sessionId + * @return Response for success or failure + */ @DELETE @Path("/{id}/sequence") - public Response deleteSequence(@PathParam("id") long partId, - @QueryParam("sid") String sessionId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response deleteSequence(@PathParam("id") final long partId, + @QueryParam("sid") final String sessionId) { + final String userId = getUserId(sessionId); try { - if (sequenceController.deleteSequence(userId, partId)) + if (sequenceController.deleteSequence(userId, partId)) { return Response.ok().build(); + } return Response.serverError().build(); - } catch (RuntimeException e) { + } catch (final RuntimeException e) { Logger.error(e); return Response.serverError().build(); } } + /** + * @param info + * @param partData + * @return created part data + */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public PartData create(@Context UriInfo info, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - PartData partData) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - EntryCreator creator = new EntryCreator(); - long id = creator.createPart(userId, partData); + public PartData create(@Context UriInfo info, PartData partData) { + final String userId = getUserId(); + final EntryCreator creator = new EntryCreator(); + final long id = creator.createPart(userId, partData); log(userId, "created entry " + id); partData.setId(id); return partData; } + /** + * @param partData + * @return created part data + */ @PUT @Path("/transfer") @Consumes(MediaType.APPLICATION_JSON) @@ -451,57 +595,67 @@ public Response transfer(PartData partData) { return super.respond(response); } + /** + * @param info + * @param partId + * @param partData + * @return updated part data + */ @PUT @Path("/{id}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public PartData update(@Context UriInfo info, - @PathParam("id") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - PartData partData) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - long id = controller.updatePart(userId, partId, partData); + public PartData update(@Context final UriInfo info, @PathParam("id") final long partId, + final PartData partData) { + final String userId = getUserId(); + final long id = controller.updatePart(userId, partId, partData); log(userId, "updated entry " + id); partData.setId(id); return partData; } + /** + * @param id + */ @DELETE @Path("/{id}") - public void delete(@PathParam("id") long id) { + public void delete(@PathParam("id") final long id) { Logger.info("Deleting part " + id); + // TODO this does nothing but log? } + /** + * @param list + * @return Response for success or failure + */ @POST @Path("/trash") @Consumes(MediaType.APPLICATION_JSON) - public Response moveToTrash(ArrayList list, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - Type fooType = new TypeToken>() { + public Response moveToTrash(final ArrayList list) { + final String userId = getUserId(); + final Type fooType = new TypeToken>() { }.getType(); - Gson gson = new GsonBuilder().create(); - ArrayList data = gson.fromJson(gson.toJsonTree(list), fooType); - boolean success = controller.moveEntriesToTrash(userId, data); + final Gson gson = new GsonBuilder().create(); + final ArrayList data = gson.fromJson(gson.toJsonTree(list), fooType); + final boolean success = controller.moveEntriesToTrash(userId, data); return respond(success); } /** * Removes the linkId from id * - * @param partId id of entry whose link we are removing + * @param partId + * id of entry whose link we are removing * @param linkedPart - * @param sessionId - * @return + * @return Response for success or failure */ @DELETE @Path("/{id}/links/{linkedId}") - public Response deleteLink(@PathParam("id") long partId, - @PathParam("linkedId") long linkedPart, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public Response deleteLink(@PathParam("id") final long partId, + @PathParam("linkedId") final long linkedPart) { + final String userId = getUserId(); log(userId, "removing link " + linkedPart + " from " + partId); - boolean success = controller.removeLink(userId, partId, linkedPart); + final boolean success = controller.removeLink(userId, partId, linkedPart); return respond(success); } diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index 5e28a7858..515708ea6 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -100,6 +100,33 @@ protected String getUserId() { return userId; } + /** + * Extract the User ID from a query parameter value or header values in the resource request. + * + * @param sessionId + * a session ID sent via query parameters + * @return a string User ID + * @throws WebApplicationException + * for unauthorized access + */ + protected String getUserId(final String sessionId) { + final Authorization auth; + if (userId != null) { + // we've already looked up the userId + return userId; + } else if ((userId = SessionHandler.getUserIdBySession(sessionId)) != null) { + // try to get user from a session ID, continue to Authorization if fails + } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { + userId = auth.getUserId(); + // TODO validation of meaningful userId + // e.g. "admin" account on EDD won't mean anything to ICE + } + if (userId == null) { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + return userId; + } + /** * @param sessionHeader * not used From a6c6dc9aa7e5762c1379b98932dd8d09450c7509 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 2 Apr 2015 19:04:44 -0700 Subject: [PATCH 23/67] Converted remaining resources --- .../ice/services/rest/PermissionResource.java | 20 +- .../services/rest/RemoteAccessResource.java | 97 ++++--- .../ice/services/rest/SampleResource.java | 161 +++++++----- .../jbei/ice/services/rest/UserResource.java | 246 +++++++++++------- .../jbei/ice/services/rest/WebResource.java | 205 +++++++++------ 5 files changed, 460 insertions(+), 269 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/PermissionResource.java b/src/main/java/org/jbei/ice/services/rest/PermissionResource.java index e2f9f7686..0a4ccb7d3 100644 --- a/src/main/java/org/jbei/ice/services/rest/PermissionResource.java +++ b/src/main/java/org/jbei/ice/services/rest/PermissionResource.java @@ -1,9 +1,9 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; + import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; @@ -21,16 +21,22 @@ public class PermissionResource extends RestResource { private PermissionsController controller = new PermissionsController(); + /** + * @param val + * @param limit + * @return matching groups and users for autocomplete widget + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") - public Response autoComplete(@QueryParam("val") String val, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @DefaultValue("8") @QueryParam("limit") int limit) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - ArrayList result = controller.getMatchingGroupsOrUsers(userId, val, limit); - if (result == null) + public Response autoComplete(@QueryParam("val") final String val, + @DefaultValue("8") @QueryParam("limit") final int limit) { + final String userId = getUserId(); + final ArrayList result = controller.getMatchingGroupsOrUsers(userId, val, + limit); + if (result == null) { return super.respond(Response.Status.INTERNAL_SERVER_ERROR); + } return super.respond(Response.Status.OK, result); } } diff --git a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java index 3358f63c5..624d75f0c 100644 --- a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java @@ -1,9 +1,9 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; + import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -20,9 +20,8 @@ import org.jbei.ice.lib.vo.FeaturedDNASequence; /** - * REST resource for sending/retrieving messages from remote - * ICE instances. Local instances access this resource which contacts the remote - * resource on its behalf + * REST resource for sending/retrieving messages from remote ICE instances. Local instances access + * this resource which contacts the remote resource on its behalf * * @author Hector Plahar */ @@ -32,77 +31,111 @@ public class RemoteAccessResource extends RestResource { private RemoteAccessController controller = new RemoteAccessController(); /** - * @param remoteId unique identifier for remote partner being accessed + * @param remoteId + * unique identifier for remote partner being accessed * @return list of available folders that are available on the registry */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/available") - public ArrayList readRemoteUser(@PathParam("id") long remoteId) { + public ArrayList readRemoteUser(@PathParam("id") final long remoteId) { return controller.getAvailableFolders(remoteId); } + /** + * @param remoteId + * @param email + * @return user from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/users/{email}") - public AccountTransfer getRemoteUser(@PathParam("id") long remoteId, - @PathParam("email") String email) { + public AccountTransfer getRemoteUser(@PathParam("id") final long remoteId, + @PathParam("email") final String email) { return controller.getRemoteUser(remoteId, email); } + /** + * @param remoteId + * @param partId + * @return sequence from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{entryId}/sequence") - public Response getSequence(@PathParam("id") long remoteId, - @PathParam("entryId") long partId) { - FeaturedDNASequence sequence = controller.getRemoteSequence(remoteId, partId); - if (sequence == null) + public Response getSequence(@PathParam("id") final long remoteId, + @PathParam("entryId") final long partId) { + final FeaturedDNASequence sequence = controller.getRemoteSequence(remoteId, partId); + if (sequence == null) { return Response.status(Response.Status.NO_CONTENT).build(); + } return Response.status(Response.Status.OK).entity(sequence).build(); } + /** + * @param remoteId + * @param partId + * @return traces from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{entryId}/traces") - public Response getSequenceTraces(@PathParam("id") long remoteId, - @PathParam("entryId") long partId) { - ArrayList traces = controller.getRemoteTraces(remoteId, partId); - if (traces == null) + public Response getSequenceTraces(@PathParam("id") final long remoteId, + @PathParam("entryId") final long partId) { + final ArrayList traces = controller + .getRemoteTraces(remoteId, partId); + if (traces == null) { return Response.status(Response.Status.NO_CONTENT).build(); + } return Response.status(Response.Status.OK).entity(traces).build(); } + /** + * @param remoteId + * @param folderId + * @param offset + * @param limit + * @param sort + * @param asc + * @return public folders from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/folders/{folderId}") - public FolderDetails getPublicFolderEntries( - @PathParam("id") long remoteId, - @PathParam("folderId") long folderId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public FolderDetails getPublicFolderEntries(@PathParam("id") final long remoteId, + @PathParam("folderId") final long folderId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { return controller.getPublicFolderEntries(remoteId, folderId, sort, asc, offset, limit); } + /** + * @param remoteId + * @param partId + * @return part samples from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{partId}/samples") - public Response getRemotePartSamples(@PathParam("id") long remoteId, - @PathParam("partId") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - ArrayList result = controller.getRemotePartSamples(remoteId, partId); + public Response getRemotePartSamples(@PathParam("id") final long remoteId, + @PathParam("partId") final long partId) { + final ArrayList result = controller.getRemotePartSamples(remoteId, partId); return super.respond(result); } + /** + * @param remoteId + * @param partId + * @return comments from remote ICE + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{partId}/comments") - public Response getRemotePartComments(@PathParam("id") long remoteId, - @PathParam("partId") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - ArrayList result = controller.getRemotePartComments(remoteId, partId); + public Response getRemotePartComments(@PathParam("id") final long remoteId, + @PathParam("partId") final long partId) { + final ArrayList result = controller.getRemotePartComments(remoteId, partId); return super.respond(result); } } diff --git a/src/main/java/org/jbei/ice/services/rest/SampleResource.java b/src/main/java/org/jbei/ice/services/rest/SampleResource.java index 2ef01c76d..ecf416c61 100644 --- a/src/main/java/org/jbei/ice/services/rest/SampleResource.java +++ b/src/main/java/org/jbei/ice/services/rest/SampleResource.java @@ -1,5 +1,20 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dto.StorageLocation; import org.jbei.ice.lib.dto.sample.PartSample; @@ -9,12 +24,6 @@ import org.jbei.ice.lib.entry.sample.RequestRetriever; import org.jbei.ice.lib.entry.sample.SampleController; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.ArrayList; -import java.util.List; - /** * REST Resource for samples * @@ -26,120 +35,154 @@ public class SampleResource extends RestResource { private RequestRetriever requestRetriever = new RequestRetriever(); private SampleController sampleController = new SampleController(); + /** + * @param token + * @return Response with matching part sample + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("{token}") - public Response getSampleByToken(@PathParam("token") String token) { + public Response getSampleByToken(@PathParam("token") final String token) { try { - ArrayList result = sampleController.getSamplesByBarcode(null, token); + final ArrayList result = sampleController.getSamplesByBarcode(null, token); return super.respond(result); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return super.respond(false); } } + /** + * @param offset + * @param limit + * @param sort + * @param asc + * @param filter + * @param status + * @return Response with matching samples + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/requests") - public Response getRequests( - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("requested") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @QueryParam("filter") String filter, - @QueryParam("status") SampleRequestStatus status, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response getRequests(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("requested") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc, + @QueryParam("filter") final String filter, + @QueryParam("status") final SampleRequestStatus status) { + final String userId = getUserId(); Logger.info(userId + ": retrieving sample requests"); - UserSamples samples = requestRetriever.getRequests(userId, offset, limit, sort, asc, status, filter); + final UserSamples samples = requestRetriever.getRequests(userId, offset, limit, sort, asc, + status, filter); return super.respond(Response.Status.OK, samples); } /** - * Sets the status of sample requests. Must have admin privs to set the sample for others - * This is intended for requesting samples + * Sets the status of sample requests. Must have admin privs to set the sample for others This + * is intended for requesting samples * - * @param sessionId session identifier + * @param status + * @param requestIds + * @return Response success or failure */ @PUT @Path("/requests") - public Response setRequestStatus( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @QueryParam("status") SampleRequestStatus status, - ArrayList requestIds) { - String userId = getUserIdFromSessionHeader(sessionId); + public Response setRequestStatus(@QueryParam("status") final SampleRequestStatus status, + final ArrayList requestIds) { + final String userId = getUserId(); try { - if (requestIds == null || requestIds.isEmpty()) + if (requestIds == null || requestIds.isEmpty()) { return super.respond(Response.Status.OK); + } - ArrayList sampleRequestIds = new ArrayList<>(); - for (Number number : requestIds) + final ArrayList sampleRequestIds = new ArrayList<>(); + for (final Number number : requestIds) { sampleRequestIds.add(number.longValue()); + } - boolean success = requestRetriever.setRequestsStatus(userId, sampleRequestIds, status); + final boolean success = requestRetriever.setRequestsStatus(userId, sampleRequestIds, + status); return super.respond(success); - } catch (Exception e) { + } catch (final Exception e) { Logger.error(e); return super.respond(Response.Status.INTERNAL_SERVER_ERROR); } } + /** + * @param requestId + * @return Response with the removed sample + */ @DELETE @Path("/requests/{id}") - public Response deleteSampleRequest(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @PathParam("id") long requestId) { - String userId = getUserIdFromSessionHeader(sessionId); + public Response deleteSampleRequest(@PathParam("id") final long requestId) { + final String userId = getUserId(); return respond(Response.Status.OK, requestRetriever.removeSampleFromCart(userId, requestId)); } + /** + * @param requestId + * @param status + * @return Response with the updated sample request + */ @PUT @Path("/requests/{id}") - public Response updateSampleRequest( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @PathParam("id") long requestId, - @QueryParam("status") SampleRequestStatus status) { - String userId = getUserIdFromSessionHeader(sessionId); - SampleRequest request = requestRetriever.updateStatus(userId, requestId, status); + public Response updateSampleRequest(@PathParam("id") final long requestId, + @QueryParam("status") final SampleRequestStatus status) { + final String userId = getUserId(); + final SampleRequest request = requestRetriever.updateStatus(userId, requestId, status); return respond(Response.Status.OK, request); } + /** + * @param offset + * @param limit + * @param sort + * @param asc + * @param uid + * @param status + * @return response with the matching sample requests + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/requests/{userId}") - public Response getUserRequests( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("requested") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @PathParam("userId") long uid, - @DefaultValue("IN_CART") @QueryParam("status") SampleRequestStatus status) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public Response getUserRequests(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("requested") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc, + @PathParam("userId") final long uid, + @DefaultValue("IN_CART") @QueryParam("status") final SampleRequestStatus status) { + final String userId = getUserId(); Logger.info(userId + ": retrieving sample requests for user"); - UserSamples userSamples = requestRetriever.getUserSamples(userId, status, offset, limit, sort, asc); + final UserSamples userSamples = requestRetriever.getUserSamples(userId, status, offset, + limit, sort, asc); return super.respond(Response.Status.OK, userSamples); } + /** + * @param request + * @return Response with the added sample requests + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/requests") - public ArrayList addRequest( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - SampleRequest request) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList addRequest(final SampleRequest request) { + final String userId = getUserId(); log(userId, "add sample request to cart for " + request.getPartData().getId()); return requestRetriever.placeSampleInCart(userId, request); } + /** + * @param type + * @return Response with the current sample requests + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/storage/{type}") public Response getSampleStorageType( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - @DefaultValue("IN_CART") @QueryParam("type") String type) { - String userId = getUserIdFromSessionHeader(userAgentHeader); - List locations = sampleController.getStorageLocations(userId, type); + @DefaultValue("IN_CART") @QueryParam("type") final String type) { + final String userId = getUserId(); + final List locations = sampleController.getStorageLocations(userId, type); return respond(locations); } } diff --git a/src/main/java/org/jbei/ice/services/rest/UserResource.java b/src/main/java/org/jbei/ice/services/rest/UserResource.java index 4653cb2b5..5ad91f815 100644 --- a/src/main/java/org/jbei/ice/services/rest/UserResource.java +++ b/src/main/java/org/jbei/ice/services/rest/UserResource.java @@ -1,5 +1,22 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.jbei.ice.lib.account.AccountController; import org.jbei.ice.lib.account.AccountTransfer; import org.jbei.ice.lib.account.PreferencesController; @@ -17,14 +34,6 @@ import org.jbei.ice.lib.group.GroupController; import org.jbei.ice.lib.shared.ColumnField; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; -import java.util.List; - /** * REST Resource for users * @@ -38,21 +47,22 @@ public class UserResource extends RestResource { private RequestRetriever requestRetriever = new RequestRetriever(); /** - * Retrieves list of users that are available to user making request. Availability is - * defined by being in the same group if the user does not have admin privileges. + * Retrieves list of users that are available to user making request. Availability is defined by + * being in the same group if the user does not have admin privileges. * - * @param sessionId unique user session identifier + * @param offset + * @param limit + * @param sort + * @param asc * @return wrapper around list of users */ @GET @Produces(MediaType.APPLICATION_JSON) - public AccountResults get( - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("lastName") @QueryParam("sort") String sort, - @DefaultValue("true") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + public AccountResults get(@DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("lastName") @QueryParam("sort") final String sort, + @DefaultValue("true") @QueryParam("asc") final boolean asc) { + final String userId = getUserId(); log(userId, "retrieving available accounts"); return groupController.getAvailableAccounts(userId, offset, limit, asc, sort); } @@ -60,159 +70,215 @@ public AccountResults get( /** * Retrieves (up to specified limit), the list of users that match the value * - * @param val text to match against users - * @param limit upper limit for number of users to return - * @param sessionId unique user session identifier + * @param val + * text to match against users + * @param limit + * upper limit for number of users to return * @return list of matching users */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") public ArrayList getAutoCompleteForAvailableAccounts( - @QueryParam("val") String val, - @DefaultValue("8") @QueryParam("limit") int limit, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + @QueryParam("val") final String val, + @DefaultValue("8") @QueryParam("limit") final int limit) { + final String userId = getUserId(); return controller.getMatchingAccounts(userId, val, limit); } + /** + * @param info + * @param userId + * @return account information for transfer + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public AccountTransfer read(@Context UriInfo info, @PathParam("id") String userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + public AccountTransfer read(@Context final UriInfo info, @PathParam("id") final String userId) { Account account; - if (userId.matches("\\d+(\\.\\d+)?")) + if (userId.matches("\\d+(\\.\\d+)?")) { account = controller.get(Long.decode(userId)); - else + } else { account = controller.getByEmail(userId); + } - if (account != null) + if (account != null) { return account.toDataTransferObject(); + } return null; } + /** + * @param info + * @param userId + * @return group listing for a user + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/groups") - public ArrayList getProfileGroups(@Context UriInfo info, @PathParam("id") long userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); + public ArrayList getProfileGroups(@Context final UriInfo info, + @PathParam("id") final long userId) { + final String userIdString = getUserId(); return groupController.retrieveUserGroups(userIdString, userId, false); } + /** + * @param userId + * @param userGroup + * @return created group + */ @PUT @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/groups") - public UserGroup createGroup(@PathParam("id") long userId, - UserGroup userGroup, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); + public UserGroup createGroup(@PathParam("id") final long userId, final UserGroup userGroup) { + final String userIdString = getUserId(); return groupController.createGroup(userIdString, userGroup); } + /** + * @param info + * @param userId + * @param offset + * @param limit + * @param sort + * @param asc + * @return collection for user's part entries + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") - public FolderDetails getProfileEntries(@Context UriInfo info, - @PathParam("id") long userId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); - EntryController entryController = new EntryController(); - ColumnField field = ColumnField.valueOf(sort.toUpperCase()); - - Account requestAccount = DAOFactory.getAccountDAO().get(userId); - List entries = entryController.retrieveOwnerEntries(userIdString, requestAccount.getEmail(), field, - asc, offset, limit); - long count = entryController.getNumberOfOwnerEntries(userIdString, requestAccount.getEmail()); - FolderDetails details = new FolderDetails(); + public FolderDetails getProfileEntries(@Context final UriInfo info, + @PathParam("id") final long userId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { + final String userIdString = getUserId(); + final EntryController entryController = new EntryController(); + final ColumnField field = ColumnField.valueOf(sort.toUpperCase()); + + final Account requestAccount = DAOFactory.getAccountDAO().get(userId); + final List entries = entryController.retrieveOwnerEntries(userIdString, + requestAccount.getEmail(), field, asc, offset, limit); + final long count = entryController.getNumberOfOwnerEntries(userIdString, + requestAccount.getEmail()); + final FolderDetails details = new FolderDetails(); details.getEntries().addAll(entries); details.setCount(count); return details; } + /** + * @param info + * @param userId + * @return preferences for a user + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/preferences") - public UserPreferences getUserPreferences(@Context UriInfo info, - @PathParam("id") long userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); - PreferencesController preferencesController = new PreferencesController(); + public UserPreferences getUserPreferences(@Context final UriInfo info, + @PathParam("id") final long userId) { + final String userIdString = getUserId(); + final PreferencesController preferencesController = new PreferencesController(); return preferencesController.getUserPreferences(userIdString, userId); } + /** + * @param userId + * @param key + * @param value + * @return updated preferences for a user + */ @POST @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/preferences/{key}") - public PreferenceInfo updatePreference( - @PathParam("id") long userId, - @PathParam("key") String key, - @QueryParam("value") String value, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String userIdString = getUserIdFromSessionHeader(userAgentHeader); - PreferencesController preferencesController = new PreferencesController(); + public PreferenceInfo updatePreference(@PathParam("id") final long userId, + @PathParam("key") final String key, @QueryParam("value") final String value) { + final String userIdString = getUserId(); + final PreferencesController preferencesController = new PreferencesController(); return preferencesController.updatePreference(userIdString, userId, key, value); } + /** + * @param info + * @param userId + * @param transfer + * @return updated user information + */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/{id}") - public AccountTransfer update(@Context UriInfo info, @PathParam("id") long userId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader, - AccountTransfer transfer) { - String user = getUserIdFromSessionHeader(userAgentHeader); + public AccountTransfer update(@Context final UriInfo info, @PathParam("id") final long userId, + final AccountTransfer transfer) { + final String user = getUserId(); return controller.updateAccount(user, userId, transfer); } + /** + * @param info + * @param transfer + * @return Response for success or failure + */ @POST @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/password") - public Response resetPassword(@Context UriInfo info, AccountTransfer transfer) { - boolean success = controller.resetPassword(transfer.getEmail()); - if (!success) + public Response resetPassword(@Context final UriInfo info, final AccountTransfer transfer) { + final boolean success = controller.resetPassword(transfer.getEmail()); + if (!success) { return super.respond(Response.Status.NOT_FOUND); + } return super.respond(Response.Status.OK); } + /** + * @param transfer + * @return updated user information + */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/password") - public AccountTransfer updatePassword( - @HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - AccountTransfer transfer) { - String user = getUserIdFromSessionHeader(sessionId); + public AccountTransfer updatePassword(final AccountTransfer transfer) { + final String user = getUserId(); return controller.updatePassword(user, transfer); } + /** + * @param accountTransfer + * @return Response with created user information + */ @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response createNewUser(AccountTransfer accountTransfer) { - accountTransfer = controller.createNewAccount(accountTransfer, true); - return super.respond(accountTransfer); + public Response createNewUser(final AccountTransfer accountTransfer) { + final AccountTransfer created = controller.createNewAccount(accountTransfer, true); + return super.respond(created); } + /** + * @param userId + * @param offset + * @param limit + * @param sort + * @param asc + * @param uid + * @param status + * @return Response with user's samples + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/samples") - public Response getRequestedSamples(@PathParam("id") long userId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("requested") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @PathParam("userId") long uid, - @DefaultValue("") @QueryParam("status") SampleRequestStatus status, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { - String user = getUserIdFromSessionHeader(userAgentHeader); - return super.respond(Response.Status.OK, requestRetriever.getUserSamples(user, status, offset, limit, sort, - asc)); + public Response getRequestedSamples(@PathParam("id") final long userId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("requested") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc, + @PathParam("userId") final long uid, + @DefaultValue("") @QueryParam("status") final SampleRequestStatus status) { + final String user = getUserId(); + return super.respond(Response.Status.OK, + requestRetriever.getUserSamples(user, status, offset, limit, sort, asc)); } } diff --git a/src/main/java/org/jbei/ice/services/rest/WebResource.java b/src/main/java/org/jbei/ice/services/rest/WebResource.java index ab00b7167..447f41e7b 100644 --- a/src/main/java/org/jbei/ice/services/rest/WebResource.java +++ b/src/main/java/org/jbei/ice/services/rest/WebResource.java @@ -1,5 +1,21 @@ package org.jbei.ice.services.rest; +import java.util.ArrayList; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + import org.hsqldb.lib.StringUtil; import org.jbei.ice.lib.dto.entry.AttachmentInfo; import org.jbei.ice.lib.dto.entry.PartData; @@ -12,13 +28,6 @@ import org.jbei.ice.lib.net.WoRController; import org.jbei.ice.lib.vo.FeaturedDNASequence; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import java.util.ArrayList; - /** * Resource for web of registries requests * @@ -31,19 +40,17 @@ public class WebResource extends RestResource { private final RemoteEntries remoteEntries = new RemoteEntries(); /** - * Retrieves information on other ice instances that is in a web of registries - * configuration with this instance; also know as registry partners + * Retrieves information on other ice instances that is in a web of registries configuration + * with this instance; also know as registry partners * - * @param approvedOnly if true (default), only instances that have been approved are returned - * @param userAgentHeader session id for user logged in user + * @param approvedOnly + * if true, only instances that have been approved are returned; defaults to true * @return wrapper around the list of registry partners */ @GET @Produces(MediaType.APPLICATION_JSON) - public Response query( - @DefaultValue("true") @QueryParam("approved_only") boolean approvedOnly, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String userAgentHeader) { - getUserIdFromSessionHeader(userAgentHeader); + public Response query(@DefaultValue("true") @QueryParam("approved_only") boolean approvedOnly) { + getUserId(); // ensure valid session or auth header return super.respond(controller.getRegistryPartners(approvedOnly)); } @@ -55,115 +62,143 @@ public Response query( * @param limit maximum number of entries to retrieve * @param sort field to sort on * @param asc sort order - * @param sessionId unique identifier for user making request - * @return OK HTTP status with the list of entries wrapped in a result object + * + * @return Response with public entries from registry partners */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries") public Response getWebEntries( - @PathParam("id") long partnerId, - @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("15") @QueryParam("limit") int limit, - @DefaultValue("created") @QueryParam("sort") String sort, - @DefaultValue("false") @QueryParam("asc") boolean asc, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - WebEntries result = remoteEntries.getPublicEntries(userId, partnerId, offset, limit, sort, asc); + @PathParam("id") final long partnerId, + @DefaultValue("0") @QueryParam("offset") final int offset, + @DefaultValue("15") @QueryParam("limit") final int limit, + @DefaultValue("created") @QueryParam("sort") final String sort, + @DefaultValue("false") @QueryParam("asc") final boolean asc) { + final String userId = getUserId(); + final WebEntries result = remoteEntries.getPublicEntries(userId, partnerId, offset, limit, sort, asc); return super.respond(Response.Status.OK, result); } + /** + * @param partnerId + * @param partId + * @return attachment info on a registry partner entry + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/attachments") - public ArrayList getAttachments( - @PathParam("id") long partnerId, - @PathParam("entryId") long partId, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String userAgentHeader) { - String userId = getUserIdFromSessionHeader(userAgentHeader); + public List getAttachments(@PathParam("id") final long partnerId, + @PathParam("entryId") final long partId) { + final String userId = getUserId(); return remoteEntries.getEntryAttachments(userId, partnerId, partId); } + /** + * @param remoteId + * @param entrySelection + * @return Response for success + */ @POST @Path("/{id}/transfer") - public Response transferEntries( - @PathParam("id") long remoteId, - EntrySelection entrySelection, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = super.getUserIdFromSessionHeader(sessionId); + public Response transferEntries(@PathParam("id") final long remoteId, + final EntrySelection entrySelection) { + final String userId = super.getUserId(); remoteEntries.transferEntries(userId, remoteId, entrySelection); return super.respond(Response.Status.OK); } + /** + * @param partnerId + * @param entryId + * @return Response with a specific entry for a registry partner + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}") - public Response getWebEntry(@Context UriInfo uriInfo, - @PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = super.getUserIdFromSessionHeader(sessionId); - PartData result = remoteEntries.getPublicEntry(userId, partnerId, entryId); + public Response getWebEntry( + @PathParam("id") final long partnerId, @PathParam("entryId") final long entryId) { + final String userId = super.getUserId(); + final PartData result = remoteEntries.getPublicEntry(userId, partnerId, entryId); return super.respond(Response.Status.OK, result); } + /** + * @param partnerId + * @param entryId + * @return Response with a specific entry tooltip for a registry partner + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/tooltip") - public Response getWebEntryTooltip(@Context UriInfo uriInfo, - @PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = super.getUserIdFromSessionHeader(sessionId); - PartData result = remoteEntries.getPublicEntryTooltip(userId, partnerId, entryId); + public Response getWebEntryTooltip( + @PathParam("id") final long partnerId, @PathParam("entryId") final long entryId) { + final String userId = super.getUserId(); + final PartData result = remoteEntries.getPublicEntryTooltip(userId, partnerId, entryId); return super.respond(Response.Status.OK, result); } + /** + * @param partnerId + * @param entryId + * @return Response with statistics on a specific entry for a registry partner + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/statistics") - public Response getStatistics(@PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = super.getUserIdFromSessionHeader(sessionId); - PartStatistics statistics = remoteEntries.getPublicEntryStatistics(userId, partnerId, entryId); + public Response getStatistics(@PathParam("id") final long partnerId, + @PathParam("entryId") final long entryId) { + final String userId = super.getUserId(); + final PartStatistics statistics = remoteEntries.getPublicEntryStatistics(userId, partnerId, entryId); return super.respond(statistics); } + /** + * @param partnerId + * @param entryId + * @return Response with a sequence on a registry partner entry + */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{id}/entries/{entryId}/sequence") - public Response getWebEntrySequence(@Context UriInfo uriInfo, - @PathParam("id") long partnerId, - @PathParam("entryId") long entryId, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = super.getUserIdFromSessionHeader(sessionId); - FeaturedDNASequence result = remoteEntries.getPublicEntrySequence(userId, partnerId, entryId); + public Response getWebEntrySequence( + @PathParam("id") final long partnerId, @PathParam("entryId") final long entryId) { + final String userId = super.getUserId(); + final FeaturedDNASequence result = remoteEntries.getPublicEntrySequence(userId, partnerId, entryId); return super.respond(Response.Status.OK, result); } + /** + * @param info + * @param partner + * @return Response with an added registry partner + */ @POST @Path("/partner") // admin function - public Response addWebPartner(@Context UriInfo info, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId, - RegistryPartner partner) { - String userId = getUserIdFromSessionHeader(sessionId); - RemoteContact contactRemote = new RemoteContact(); - RegistryPartner registryPartner = contactRemote.addWebPartner(userId, partner); + public Response addWebPartner(final RegistryPartner partner) { + final String userId = getUserId(); + final RemoteContact contactRemote = new RemoteContact(); + final RegistryPartner registryPartner = contactRemote.addWebPartner(userId, partner); return respond(Response.Status.OK, registryPartner); } + /** + * @param info + * @param partnerId + * @return Response with registry partner info + */ @GET @Path("/partner/{id}") - public Response getWebPartner(@Context UriInfo info, - @PathParam("id") long partnerId, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - RegistryPartner partner = controller.getWebPartner(userId, partnerId); + public Response getWebPartner(@Context final UriInfo info, @PathParam("id") final long partnerId) { + final String userId = getUserId(); + final RegistryPartner partner = controller.getWebPartner(userId, partnerId); return super.respond(Response.Status.OK, partner); } + /** + * @param partner + * @return Response for success or failure + */ @POST @Path("/partner/remote") public Response remoteWebPartnerRequest(RegistryPartner partner) { @@ -185,31 +220,39 @@ public Response remoteWebPartnerRemoveRequest( public Response getWebPartners(@HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId, @HeaderParam(WOR_PARTNER_TOKEN) String worToken, @QueryParam("url") String url) { - if (StringUtil.isEmpty(sessionId)) + if (!StringUtil.isEmpty(worToken)) return super.respond(controller.getWebPartners(worToken, url)); - String userId = getUserIdFromSessionHeader(sessionId); + final String userId = getUserId(); return super.respond(controller.getWebPartners(userId)); } + /** + * @param url + * @param partner + * @return Response for success or failure + */ @PUT @Path("/partner/{url}") - public Response updateWebPartner( - @PathParam("url") String url, RegistryPartner partner, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.updateWebPartner(userId, url, partner)) + public Response updateWebPartner(@PathParam("url") final String url, + final RegistryPartner partner) { + final String userId = getUserId(); + if (controller.updateWebPartner(userId, url, partner)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } + /** + * @param url + * @return Response for success or failure + */ @DELETE @Path("/partner/{url}") - public Response removeWebPartner( - @PathParam("url") String url, - @HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); - if (controller.removeWebPartner(userId, url)) + public Response removeWebPartner(@PathParam("url") final String url) { + final String userId = getUserId(); + if (controller.removeWebPartner(userId, url)) { return respond(Response.Status.OK); + } return respond(Response.Status.INTERNAL_SERVER_ERROR); } } From 23d51fca45ef1bbd9bf931182bdeed62b4ff2606 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Tue, 7 Apr 2015 14:24:34 -0700 Subject: [PATCH 24/67] Need to explicitly begin/end transaction during initialization of KeyTable for looking up HMAC auth keys --- .../java/org/jbei/ice/services/rest/RestResource.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index 515708ea6..b81518c02 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -18,6 +18,7 @@ import org.jbei.auth.hmac.HmacSignatureFactory; import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; +import org.jbei.ice.lib.dao.hibernate.HibernateUtil; import org.jbei.ice.lib.dto.ConfigurationKey; import org.jbei.ice.lib.utils.Utils; @@ -35,8 +36,14 @@ public class RestResource { private static final KeyTable TABLE = new KeyTable() { // keys stored in /var/lib/tomcat6/data/rest-auth by default - private final File directory = Paths.get( - Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), "rest-auth").toFile(); + private final File directory; + { + // need to force-create a transaction to get the DATA_DIRECTORY config value + HibernateUtil.beginTransaction(); + directory = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + "rest-auth").toFile(); + HibernateUtil.commitTransaction(); + } @Override public Key getKey(final String keyId) { From 86a19937b25fbeb024e0a70ebe0feb8b55f40cf1 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 8 Apr 2015 18:09:14 -0700 Subject: [PATCH 25/67] Including jbei-repo for including rest-util artifact --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 991d0507f..a557eccdb 100755 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,11 @@ Sonatype OSS Snapshot Repository https://oss.sonatype.org/content/repositories/snapshots/ + + jbei-repo + JBEI Maven Repository + https://repo.jbei.org/artifactory/repo/ + From 8008cedb42b35a2735b86af65d8caa4b23c9435a Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 9 Apr 2015 13:42:12 -0700 Subject: [PATCH 26/67] Changing the repository ID to match existing settings --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a557eccdb..62c07c93e 100755 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ https://oss.sonatype.org/content/repositories/snapshots/ - jbei-repo + repo.jbei.org JBEI Maven Repository https://repo.jbei.org/artifactory/repo/ From 873853f329b5066c75c2a10e1a34fd50a3916ee7 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Fri, 10 Apr 2015 14:53:07 -0700 Subject: [PATCH 27/67] Switch out hard-coded Local auth for Ldap auth --- src/main/java/org/jbei/ice/lib/account/AccountController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/account/AccountController.java b/src/main/java/org/jbei/ice/lib/account/AccountController.java index df89777c3..7191b9e41 100755 --- a/src/main/java/org/jbei/ice/lib/account/AccountController.java +++ b/src/main/java/org/jbei/ice/lib/account/AccountController.java @@ -5,7 +5,7 @@ import org.jbei.ice.lib.account.authentication.AuthenticationException; import org.jbei.ice.lib.account.authentication.IAuthentication; import org.jbei.ice.lib.account.authentication.InvalidCredentialsException; -import org.jbei.ice.lib.account.authentication.LocalAuthentication; +import org.jbei.ice.lib.account.authentication.LblLdapAuthentication; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.account.model.AccountPreferences; import org.jbei.ice.lib.common.logging.Logger; @@ -336,7 +336,7 @@ public boolean isAdministrator(String userId) { * @throws InvalidCredentialsException */ public String authenticate(String login, String password, String ip) throws InvalidCredentialsException { - IAuthentication authentication = new LocalAuthentication(); + IAuthentication authentication = new LblLdapAuthentication(); String email; try { From fed0b4532bde3497c29f1f0db29ac5edc5789871 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 15 Apr 2015 19:24:59 -0700 Subject: [PATCH 28/67] Adding truststore configuration to Jetty. --- jetty-debug.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jetty-debug.xml b/jetty-debug.xml index 3c3645caa..4f1008997 100644 --- a/jetty-debug.xml +++ b/jetty-debug.xml @@ -34,10 +34,11 @@ 8443 30000 - /.keystore - + /.keystore changeit changeit + /.keystore + changeit From 416722ee2f8e24bf9261fcfb17cbc855c07ee761 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 15 Apr 2015 19:44:03 -0700 Subject: [PATCH 29/67] Updating pom with minimum maven version, and updated minor versions of dependencies and plugins found with `mvn versions:display-dependency-updates versions:display-plugin-updates` --- pom.xml | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 62c07c93e..65b2cda15 100755 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,9 @@ 4.2.0 ice Inventory of Composable Elements (ICE) for Synthetic Biology + + 2.2.1 + biojava-maven-repo @@ -43,7 +46,7 @@ postgresql postgresql - 9.1-901.jdbc4 + 9.3-1100.jdbc41 org.hsqldb @@ -59,7 +62,7 @@ com.google.code.gson gson - 2.2.4 + 2.3.1 compile @@ -110,17 +113,27 @@ org.apache.commons commons-email - 1.3.1 + 1.3.3 net.sf.opencsv opencsv 2.3 + + org.apache.httpcomponents + httpcore + 4.4.1 + + + org.apache.httpcomponents + httpclient + 4.4.1 + ch.qos.logback logback-classic - 1.0.13 + 1.1.3 org.biojava @@ -173,7 +186,7 @@ true org.apache.maven.plugins maven-compiler-plugin - 2.3.2 + 3.3 1.7 1.7 @@ -193,7 +206,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 2.10.3 From a31fe07ddee3060606e8908f9155ac5f0fc5d496 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Wed, 15 Apr 2015 20:31:27 -0700 Subject: [PATCH 30/67] Moved HMAC authentication to a request filter/interceptor to get access to request message body before conversion to POJO entity --- .../rest/AuthenticationInterceptor.java | 125 ++++++++++++++++++ .../jbei/ice/services/rest/RestResource.java | 46 ++----- .../rest/multipart/IceApplication.java | 7 +- src/main/resources/logback.xml | 3 + 4 files changed, 146 insertions(+), 35 deletions(-) create mode 100644 src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java diff --git a/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java new file mode 100644 index 000000000..32b2415ed --- /dev/null +++ b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java @@ -0,0 +1,125 @@ +/** + * + */ +package org.jbei.ice.services.rest; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Paths; +import java.security.Key; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.jbei.auth.KeyTable; +import org.jbei.auth.hmac.HmacAuthorizor; +import org.jbei.auth.hmac.HmacSignature; +import org.jbei.auth.hmac.HmacSignatureFactory; +import org.jbei.ice.lib.dao.hibernate.HibernateUtil; +import org.jbei.ice.lib.dto.ConfigurationKey; +import org.jbei.ice.lib.utils.Utils; + +/** + * Filter watches for Authorization headers on incoming requests, and passes along data to build an + * {@link HmacSignature} to validate the request. + * + * @author wcmorrell + * @version 4.2 + * @since 4.2 + */ +@Priority(Priorities.AUTHENTICATION) +public class AuthenticationInterceptor implements ContainerRequestFilter, ReaderInterceptor { + + /** + * Property/Attribute name for mapping the expected value of the generated signature. + */ + public static final String EXPECTED_SIGNATURE = "org.jbei.auth.signature"; + + /** + * Property/Attribute name for mapping the {@link HmacSignature} object for the request. + */ + public static final String HMAC_SIGNATURE = "org.jbei.auth.hmac"; + + private static final Logger log = LoggerFactory.getLogger(HmacAuthorizor.class); + + // do lookup by using existing configuration DATA_DIRECTORY to find key names => key data + private static final KeyTable TABLE = new KeyTable() { + + // keys stored in /var/lib/tomcat6/data/rest-auth by default + private final File directory; + { + // need to force-create a transaction to get the DATA_DIRECTORY config value + HibernateUtil.beginTransaction(); + directory = Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), + "rest-auth").toFile(); + HibernateUtil.commitTransaction(); + } + + @Override + public Key getKey(final String keyId) { + try { + // find file named by keyId in the directory + final File keyFile = new File(directory, keyId); + // collect all lines in the file to a buffer + final StringBuilder encoded = new StringBuilder(); + try (final FileReader reader = new FileReader(keyFile); + final BufferedReader buffered = new BufferedReader(reader);) { + String line; + while ((line = buffered.readLine()) != null) { + encoded.append(line); + } + // after reading all lines, decode value into a Key object + return HmacSignatureFactory.decodeKey(encoded.toString()); + } + } catch (final Throwable t) { + log.error("Failed to load rest-auth key " + keyId); + } + return null; + } + + }; + + private static final HmacAuthorizor AUTHORIZOR = new HmacAuthorizor(TABLE); + + @Override + public Object aroundReadFrom(final ReaderInterceptorContext context) throws IOException, + WebApplicationException { + final Object hmac = context.getProperty(HMAC_SIGNATURE); + if (hmac != null && hmac instanceof HmacSignature) { + context.setInputStream(((HmacSignature) hmac).filterInput(context.getInputStream())); + } + return context.proceed(); + } + + @Override + public void filter(final ContainerRequestContext requestContext) throws IOException { + final String hmac = requestContext.getHeaderString("Authorization"); + final String[] parts = StringUtils.split(hmac, ':'); + if (parts == null || parts.length == 0) { + log.debug("No Authorization header found on request"); + } else if (!"1".equals(parts[0]) || parts.length != 4) { + log.debug("Unknown Authorization header format"); + } else { + final UriInfo uriInfo = requestContext.getUriInfo(); + final MultivaluedMap params = uriInfo.getQueryParameters(false); + final HmacSignature sig = AUTHORIZOR.initSignature(hmac, requestContext.getMethod(), + requestContext.getHeaderString("Host"), uriInfo.getPath(), params); + requestContext.setProperty(HMAC_SIGNATURE, sig); + requestContext.setProperty(EXPECTED_SIGNATURE, parts[3]); + } + } + +} diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index b81518c02..db18bccfc 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -1,26 +1,14 @@ package org.jbei.ice.services.rest; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.nio.file.Paths; -import java.security.Key; - import javax.servlet.http.HttpServletRequest; import javax.ws.rs.HeaderParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; -import org.jbei.auth.Authorization; -import org.jbei.auth.KeyTable; -import org.jbei.auth.hmac.HmacAuthorizor; -import org.jbei.auth.hmac.HmacSignatureFactory; +import org.jbei.auth.hmac.HmacSignature; import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; -import org.jbei.ice.lib.dao.hibernate.HibernateUtil; -import org.jbei.ice.lib.dto.ConfigurationKey; -import org.jbei.ice.lib.utils.Utils; /** * Parent class for all rest resource objects @@ -90,21 +78,7 @@ public Key getKey(final String keyId) { * for unauthorized access */ protected String getUserId() { - final Authorization auth; - if (userId != null) { - // we've already looked up the userId - return userId; - } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { - userId = auth.getUserId(); - // TODO validation of meaningful userId - // e.g. "admin" account on EDD won't mean anything to ICE - } else if (sessionId != null) { - userId = SessionHandler.getUserIdBySession(sessionId); - } - if (userId == null) { - throw new WebApplicationException(Response.Status.UNAUTHORIZED); - } - return userId; + return getUserId(sessionId); } /** @@ -117,16 +91,22 @@ protected String getUserId() { * for unauthorized access */ protected String getUserId(final String sessionId) { - final Authorization auth; if (userId != null) { // we've already looked up the userId return userId; } else if ((userId = SessionHandler.getUserIdBySession(sessionId)) != null) { // try to get user from a session ID, continue to Authorization if fails - } else if ((auth = AUTHORIZOR.validate(request)).isValid()) { - userId = auth.getUserId(); - // TODO validation of meaningful userId - // e.g. "admin" account on EDD won't mean anything to ICE + } else { + final Object hmac = request.getAttribute(AuthenticationInterceptor.HMAC_SIGNATURE); + final Object valid = request.getAttribute(AuthenticationInterceptor.EXPECTED_SIGNATURE); + if (hmac != null && hmac instanceof HmacSignature) { + final HmacSignature generated = (HmacSignature) hmac; + if (generated.generateSignature().equals(valid)) { + // TODO validation of meaningful userId + // e.g. "admin" account on EDD won't mean anything to ICE + userId = generated.getUserId(); + } + } } if (userId == null) { throw new WebApplicationException(Response.Status.UNAUTHORIZED); diff --git a/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java b/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java index 2a88b1447..a57d5cd9c 100644 --- a/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java +++ b/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java @@ -2,12 +2,14 @@ import java.util.HashSet; import java.util.Set; -import javax.ws.rs.core.Application; -import org.jbei.ice.services.rest.FileResource; +import javax.ws.rs.core.Application; import org.glassfish.jersey.media.multipart.MultiPartFeature; +import org.jbei.ice.services.rest.AuthenticationInterceptor; +import org.jbei.ice.services.rest.FileResource; + /** * @author Hector Plahar */ @@ -19,6 +21,7 @@ public Set> getClasses() { // register resources and features classes.add(MultiPartFeature.class); classes.add(FileResource.class); + classes.add(AuthenticationInterceptor.class); return classes; } } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index beb1c40cc..634ceb96d 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -17,6 +17,9 @@ + + + From 2a0db900b667365a5f4b812e7770bf28e0dd72a6 Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 16 Apr 2015 17:31:02 -0700 Subject: [PATCH 31/67] Modifying logback config again to prevent duplicate logs on the org.jbei.auth logger + root logger --- src/main/resources/logback.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 634ceb96d..3810abe3a 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -17,7 +17,7 @@ - + From 65db1e89e68208c67c6873068d17c6becfb01dce Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 16 Apr 2015 17:31:56 -0700 Subject: [PATCH 32/67] Change AccountControler to load authentication backend class from database setting, default fallback is LocalAuthentication --- .../ice/lib/account/AccountController.java | 451 ++++++++++++------ .../jbei/ice/lib/dto/ConfigurationKey.java | 4 +- .../jbei/ice/services/rest/UserResource.java | 2 +- 3 files changed, 296 insertions(+), 161 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/account/AccountController.java b/src/main/java/org/jbei/ice/lib/account/AccountController.java index 7191b9e41..c352ea1c2 100755 --- a/src/main/java/org/jbei/ice/lib/account/AccountController.java +++ b/src/main/java/org/jbei/ice/lib/account/AccountController.java @@ -1,11 +1,19 @@ package org.jbei.ice.lib.account; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Set; + import org.apache.commons.lang.StringUtils; +import org.slf4j.LoggerFactory; + import org.jbei.ice.ControllerException; import org.jbei.ice.lib.account.authentication.AuthenticationException; import org.jbei.ice.lib.account.authentication.IAuthentication; -import org.jbei.ice.lib.account.authentication.InvalidCredentialsException; -import org.jbei.ice.lib.account.authentication.LblLdapAuthentication; +import org.jbei.ice.lib.account.authentication.LocalAuthentication; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.account.model.AccountPreferences; import org.jbei.ice.lib.common.logging.Logger; @@ -20,48 +28,60 @@ import org.jbei.ice.lib.utils.Emailer; import org.jbei.ice.lib.utils.Utils; -import java.text.SimpleDateFormat; -import java.util.*; - /** * ABI to manipulate {@link Account} objects. *

- * This class contains methods that wrap {@link org.jbei.ice.lib.dao.hibernate.AccountDAO} to manipulate {@link - * Account} - * objects. + * This class contains methods that wrap {@link org.jbei.ice.lib.dao.hibernate.AccountDAO} to + * manipulate {@link Account} objects. * * @author Timothy Ham, Zinovii Dmytriv, Hector Plahar */ public class AccountController { + private static final org.slf4j.Logger log = LoggerFactory.getLogger(AccountController.class); private static final String ADMIN_ACCOUNT_EMAIL = "Administrator"; private static final String ADMIN_ACCOUNT_PASSWORD = "Administrator"; private final AccountDAO dao; private final AccountPreferencesDAO accountPreferencesDAO; + /** + * Default constructor. + */ public AccountController() { dao = DAOFactory.getAccountDAO(); accountPreferencesDAO = DAOFactory.getAccountPreferencesDAO(); } - public AccountTransfer updateAccount(String requester, long userId, AccountTransfer transfer) { - Account account = dao.get(userId); - if (!account.getEmail().equalsIgnoreCase(requester) && !isAdministrator(requester)) + /** + * @param requester + * @param userId + * @param transfer + * @return updated account object + */ + public AccountTransfer updateAccount(final String requester, final long userId, + final AccountTransfer transfer) { + final Account account = dao.get(userId); + if (!account.getEmail().equalsIgnoreCase(requester) && !isAdministrator(requester)) { return null; + } // if transfer has password then it is a password change - if (!StringUtils.isEmpty(transfer.getFirstName())) + if (!StringUtils.isEmpty(transfer.getFirstName())) { account.setFirstName(transfer.getFirstName()); + } - if (!StringUtils.isEmpty(transfer.getLastName())) + if (!StringUtils.isEmpty(transfer.getLastName())) { account.setLastName(transfer.getLastName()); + } - if (!StringUtils.isEmpty(transfer.getDescription())) + if (!StringUtils.isEmpty(transfer.getDescription())) { account.setDescription(transfer.getDescription()); + } - if (!StringUtils.isEmpty(transfer.getInstitution())) + if (!StringUtils.isEmpty(transfer.getInstitution())) { account.setInstitution(transfer.getInstitution()); + } return dao.update(account).toDataTransferObject(); } @@ -69,58 +89,71 @@ public AccountTransfer updateAccount(String requester, long userId, AccountTrans /** * Retrieve account from the database by database id. * - * @param id Database id of account + * @param id + * Database id of account * @return Account for the id */ - public Account get(long id) { + public Account get(final long id) { return dao.get(id); } /** * Reset a user's password * - * @param targetEmail email address of user account to be changed - * @return true if the user account is found with email specified in the parameter and password for it is - * successfully reset, false otherwise + * @param targetEmail + * email address of user account to be changed + * @return true if the user account is found with email specified in the parameter and password + * for it is successfully reset, false otherwise */ - public boolean resetPassword(String targetEmail) { + public boolean resetPassword(final String targetEmail) { Account account = getByEmail(targetEmail); - if (account == null) + if (account == null) { return false; + } try { - String newPassword = Utils.generateUUID().substring(24); - String encryptedNewPassword = AccountUtils.encryptNewUserPassword(newPassword, account.getSalt()); + final String newPassword = Utils.generateUUID().substring(24); + final String encryptedNewPassword = AccountUtils.encryptNewUserPassword(newPassword, + account.getSalt()); account.setPassword(encryptedNewPassword); account = dao.update(account); - AccountTransfer transfer = account.toDataTransferObject(); + final AccountTransfer transfer = account.toDataTransferObject(); transfer.setPassword(newPassword); - String url = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); + final String url = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); String projectName = Utils.getConfigValue(ConfigurationKey.PROJECT_NAME); - if (StringUtils.isEmpty(projectName)) + if (StringUtils.isEmpty(projectName)) { projectName = "ICE"; - String subject = projectName + " Password Reset"; + } + final String subject = projectName + " Password Reset"; String name = account.getFirstName(); if (StringUtils.isBlank(name)) { name = account.getLastName(); } - SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, MMM d, yyyy 'at' HH:mm aaa, z"); - - StringBuilder builder = new StringBuilder(); - builder.append("Dear ").append(name).append(",\n\n") - .append("The password for your ").append(projectName) - .append(" account (").append(targetEmail).append(") was reset on ") - .append(dateFormat.format(new Date())).append(".\nYour new temporary password is\n\n") - .append(newPassword).append("\n\n") - .append("Please go to the following link to login and change your password.\n\n") - .append("https://").append(url).append("/profile/").append(account.getId()) - .append("\n\nThank you."); + final SimpleDateFormat dateFormat = new SimpleDateFormat( + "EEE, MMM d, yyyy 'at' HH:mm aaa, z"); + + final StringBuilder builder = new StringBuilder(); + builder.append("Dear ") + .append(name) + .append(",\n\n") + .append("The password for your ") + .append(projectName) + .append(" account (") + .append(targetEmail) + .append(") was reset on ") + .append(dateFormat.format(new Date())) + .append(".\nYour new temporary password is\n\n") + .append(newPassword) + .append("\n\n") + .append("Please go to the following link to login and change your password.\n\n") + .append("https://").append(url).append("/profile/").append(account.getId()) + .append("\n\nThank you."); Emailer.send(account.getEmail(), subject, builder.toString()); - } catch (Exception ex) { + } catch (final Exception ex) { Logger.error(ex); return false; } @@ -130,34 +163,47 @@ public boolean resetPassword(String targetEmail) { /** * Updates account password associated the account email. It encrypts it before associating it * with the account + * + * @param userId + * @param transfer + * @return updated account object */ - public AccountTransfer updatePassword(String userId, AccountTransfer transfer) { - Account userAccount = getByEmail(transfer.getEmail()); - if (userAccount == null) - throw new IllegalArgumentException("Could not retrieve account by id " + transfer.getEmail()); + public AccountTransfer updatePassword(final String userId, final AccountTransfer transfer) { + final Account userAccount = getByEmail(transfer.getEmail()); + if (userAccount == null) { + throw new IllegalArgumentException("Could not retrieve account by id " + + transfer.getEmail()); + } - if (!isAdministrator(userId) && !userAccount.getEmail().equalsIgnoreCase(userId)) + if (!isAdministrator(userId) && !userAccount.getEmail().equalsIgnoreCase(userId)) { return null; + } - userAccount.setPassword(AccountUtils.encryptNewUserPassword(transfer.getPassword(), userAccount.getSalt())); + userAccount.setPassword(AccountUtils.encryptNewUserPassword(transfer.getPassword(), + userAccount.getSalt())); return dao.update(userAccount).toDataTransferObject(); } /** - * validates the account dto to ensure that the fields required (especially by the database) - * are present + * validates the account dto to ensure that the fields required (especially by the database) are + * present * - * @param accountTransfer account dto for validation + * @param accountTransfer + * account dto for validation */ - private boolean validateRequiredAccountFields(AccountTransfer accountTransfer) { - if (accountTransfer.getFirstName() == null || accountTransfer.getFirstName().trim().isEmpty()) + private boolean validateRequiredAccountFields(final AccountTransfer accountTransfer) { + if (accountTransfer.getFirstName() == null + || accountTransfer.getFirstName().trim().isEmpty()) { return false; + } - if (accountTransfer.getLastName() == null || accountTransfer.getLastName().trim().isEmpty()) + if (accountTransfer.getLastName() == null || accountTransfer.getLastName().trim().isEmpty()) { return false; + } - if (accountTransfer.getEmail() == null || accountTransfer.getEmail().trim().isEmpty()) + if (accountTransfer.getEmail() == null || accountTransfer.getEmail().trim().isEmpty()) { return false; + } return true; } @@ -166,26 +212,28 @@ private boolean validateRequiredAccountFields(AccountTransfer accountTransfer) { * Creates a new account using the parameters passed. A random password is initially generated , * encrypted and assigned to the account * - * @param info contains information needed to create account - * @param sendEmail whether to send account information (including password by email) + * @param info + * contains information needed to create account + * @param sendEmail + * whether to send account information (including password by email) * @return generated password */ - public AccountTransfer createNewAccount(AccountTransfer info, boolean sendEmail) { + public AccountTransfer createNewAccount(final AccountTransfer info, final boolean sendEmail) { // validate fields required by the database validateRequiredAccountFields(info); - String email = info.getEmail().trim(); + final String email = info.getEmail().trim(); if (getByEmail(email) != null) { Logger.error("Account with id \"" + email + "\" already exists"); return null; } // generate salt and encrypt password before storing - String salt = Utils.generateSaltForUserAccount(); - String newPassword = Utils.generateUUID().substring(24); - String encryptedPassword = AccountUtils.encryptNewUserPassword(newPassword, salt); + final String salt = Utils.generateSaltForUserAccount(); + final String newPassword = Utils.generateUUID().substring(24); + final String encryptedPassword = AccountUtils.encryptNewUserPassword(newPassword, salt); - Account account = AccountUtils.fromDTO(info); + final Account account = AccountUtils.fromDTO(info); account.setPassword(encryptedPassword); account.setSalt(salt); account.setCreationTime(Calendar.getInstance().getTime()); @@ -196,24 +244,25 @@ public AccountTransfer createNewAccount(AccountTransfer info, boolean sendEmail) return info; } - String subject = "Account created successfully"; - StringBuilder stringBuilder = new StringBuilder(); + final String subject = "Account created successfully"; + final StringBuilder stringBuilder = new StringBuilder(); String name = account.getFirstName(); if (StringUtils.isBlank(name)) { name = account.getLastName(); - if (StringUtils.isBlank(name)) + if (StringUtils.isBlank(name)) { name = email; + } } stringBuilder.append("Dear ").append(name).append(", ") - .append("\n\nThank you for creating a ") - .append(Utils.getConfigValue(ConfigurationKey.PROJECT_NAME)) - .append(" account. \nBy accessing ") - .append("this site with the password provided at the bottom ") - .append("you agree to the following terms:\n\n"); + .append("\n\nThank you for creating a ") + .append(Utils.getConfigValue(ConfigurationKey.PROJECT_NAME)) + .append(" account. \nBy accessing ") + .append("this site with the password provided at the bottom ") + .append("you agree to the following terms:\n\n"); - String terms = "Biological Parts IP Disclaimer: \n\n" + final String terms = "Biological Parts IP Disclaimer: \n\n" + "The JBEI Registry of Biological Parts Software is licensed under a standard BSD\n" + "license. Permission or license to use the biological parts registered in\n" + "the JBEI Registry of Biological Parts is not included in the BSD license\n" @@ -222,26 +271,28 @@ public AccountTransfer createNewAccount(AccountTransfer info, boolean sendEmail) + "Biological Parts will not infringe any patent or other proprietary right."; stringBuilder.append(terms); - stringBuilder.append("\n\nYour new password is: ") - .append(newPassword) - .append("\nYour login id is: ") - .append(info.getEmail()) - .append("\n\n"); + stringBuilder.append("\n\nYour new password is: ").append(newPassword) + .append("\nYour login id is: ").append(info.getEmail()).append("\n\n"); - String server = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); - stringBuilder.append("Please remember to change your password by going to your profile page at \n\n") - .append("https://").append(server).append("/profile/").append(account.getId()) - .append("\n\nThank you."); + final String server = Utils.getConfigValue(ConfigurationKey.URI_PREFIX); + stringBuilder + .append("Please remember to change your password by going to your profile page at \n\n") + .append("https://").append(server).append("/profile/").append(account.getId()) + .append("\n\nThank you."); Emailer.send(info.getEmail(), subject, stringBuilder.toString()); info.setPassword(newPassword); return info; } + /** + * @return new admin account + */ public Account createAdminAccount() { Account adminAccount = getByEmail(ADMIN_ACCOUNT_EMAIL); - if (adminAccount != null) + if (adminAccount != null) { return adminAccount; + } adminAccount = new Account(); adminAccount.setEmail(ADMIN_ACCOUNT_EMAIL); @@ -250,11 +301,12 @@ public Account createAdminAccount() { adminAccount.setInitials(""); adminAccount.setInstitution(""); adminAccount.setSalt(Utils.generateSaltForUserAccount()); - adminAccount.setPassword(AccountUtils.encryptNewUserPassword(ADMIN_ACCOUNT_PASSWORD, adminAccount.getSalt())); + adminAccount.setPassword(AccountUtils.encryptNewUserPassword(ADMIN_ACCOUNT_PASSWORD, + adminAccount.getSalt())); adminAccount.setDescription("Administrator Account"); adminAccount.setIp(""); - Date currentTime = Calendar.getInstance().getTime(); + final Date currentTime = Calendar.getInstance().getTime(); adminAccount.setCreationTime(currentTime); adminAccount.setModificationTime(currentTime); adminAccount.setLastLoginTime(currentTime); @@ -265,22 +317,35 @@ public Account createAdminAccount() { /** * Retrieve {@link Account} by user id. * - * @param email unique identifier for account, typically email + * @param email + * unique identifier for account, typically email * @return {@link Account} */ - public Account getByEmail(String email) { + public Account getByEmail(final String email) { return dao.getByEmail(email); } - public long getAccountId(String email) { - Account account = dao.getByEmail(email); - if (account == null) + /** + * @param email + * an account identifier (usually email) + * @return database identifier of account matching account identifier (email) + * @throws IllegalArgumentException + * for an invalid account identifier + */ + public long getAccountId(final String email) { + final Account account = dao.getByEmail(email); + if (account == null) { throw new IllegalArgumentException("No account found with email " + email); + } return account.getId(); } - public AccountTransfer getAccountBySessionKey(String sessionKey) { - String userId = SessionHandler.getUserIdBySession(sessionKey); + /** + * @param sessionKey + * @return Account object matching a session key, or {@code null} + */ + public Account getAccountBySessionKey(final String sessionKey) { + final String userId = SessionHandler.getUserIdBySession(sessionKey); if (userId == null) { Logger.warn("Could not retrieve user id for session " + sessionKey); return null; @@ -301,66 +366,69 @@ public AccountTransfer getAccountBySessionKey(String sessionKey) { * @param account * @return {@link Account} that has been saved. */ - public Account save(Account account) { + public Account save(final Account account) { account.setModificationTime(Calendar.getInstance().getTime()); - if (account.getSalt() == null || account.getSalt().isEmpty()) + if (account.getSalt() == null || account.getSalt().isEmpty()) { account.setSalt(Utils.generateSaltForUserAccount()); + } return dao.create(account); } + /** + * @param account + * @return {@code true} if an administrator account + */ + public boolean isAdministrator(final Account account) { + return isAdministrator(account.getEmail()); + } + /** * Check in the database if an account is a moderator. * - * @param userId unique account identifier for user + * @param userId + * unique account identifier for user * @return True, if the account is a moderator. */ - public boolean isAdministrator(String userId) { - if (StringUtils.isEmpty(userId)) + public boolean isAdministrator(final String userId) { + if (StringUtils.isEmpty(userId)) { return false; + } - Account account = this.getByEmail(userId); + final Account account = getByEmail(userId); return account != null && account.getType() == AccountType.ADMIN; } /** * Authenticate a user in the database. *

- * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the settings file, - * authenticate - * the - * user, and return the sessionData + * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the + * settings file, authenticate the user, and return the sessionData * * @param login * @param password - * @param ip IP Address of the user. - * @throws InvalidCredentialsException + * @param ip + * IP Address of the user. + * @return the account identifier (email) on a successful login, otherwise {@code null} */ - public String authenticate(String login, String password, String ip) throws InvalidCredentialsException { - IAuthentication authentication = new LblLdapAuthentication(); + public String authenticate(final String login, final String password, final String ip) { + final IAuthentication authentication = getAuthenticationBackend(); String email; try { email = authentication.authenticates(login.trim(), password); if (email == null) { - try { - Thread.sleep(2000); // sets 2 seconds delay on login to prevent login/password brute force hacking - } catch (InterruptedException ie) { - Logger.warn(ie.getMessage()); - } + loginFailureCooldown(); return null; } - } catch (AuthenticationException e2) { - try { - Thread.sleep(2000); // sets 2 seconds delay on login to prevent login/password brute force hacking - } catch (InterruptedException ie) { - Logger.warn(ie.getMessage()); - } + } catch (final AuthenticationException e2) { + loginFailureCooldown(); return null; } - Account account = dao.getByEmail(email); + final Account account = dao.getByEmail(email); if (account != null) { - AccountPreferences accountPreferences = accountPreferencesDAO.getAccountPreferences(account); + AccountPreferences accountPreferences = accountPreferencesDAO + .getAccountPreferences(account); if (accountPreferences == null) { accountPreferences = new AccountPreferences(); @@ -378,49 +446,87 @@ public String authenticate(String login, String password, String ip) throws Inva return null; } + private void loginFailureCooldown() { + // sets 2 seconds delay on login to prevent login/password brute force hacking + try { + Thread.sleep(2000); + } catch (final InterruptedException ie) { + Logger.warn(ie.getMessage()); + } + } + + /** + * Attempts to load the ICE Authentication Backend from database configuration. + * + * @return an IAuthentication backend + */ + public IAuthentication getAuthenticationBackend() { + final String clazzName = Utils.getConfigValue(ConfigurationKey.AUTHENTICATION_BACKEND); + try { + final Class clazz = Class.forName(clazzName); + if (IAuthentication.class.isAssignableFrom(clazz)) { + return (IAuthentication) clazz.newInstance(); + } + } catch (final ClassNotFoundException e) { + log.error("Failed to load class " + clazzName); + } catch (final InstantiationException e) { + log.error("Failed to instantiate class " + clazzName); + } catch (final IllegalAccessException e) { + log.error("Inaccessible class " + clazzName); + } + return new LocalAuthentication(); + } + /** * Authenticate a user in the database. *

- * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the settings file, - * authenticate - * the - * user, and return the sessionData + * Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the + * settings file, authenticate the user, and return the sessionData * - * @param transfer user information containing the email and password to be used for authentication - * If the sessionId field is set, it may or may not be used as the user's session id + * @param transfer + * user information containing the email and password to be used for authentication + * If the sessionId field is set, it may or may not be used as the user's session id * @return {@link AccountTransfer} */ - public AccountTransfer authenticate(AccountTransfer transfer) { - String email; - try { - email = authenticate(transfer.getEmail(), transfer.getPassword(), ""); - } catch (InvalidCredentialsException e) { - Logger.error(e); + public AccountTransfer authenticate(final AccountTransfer transfer) { + final String email = authenticate(transfer.getEmail(), transfer.getPassword(), ""); + + if (email == null) { return null; } - if (email == null) - return null; - - Account account = dao.getByEmail(email); - if (account == null) + final Account account = dao.getByEmail(email); + if (account == null) { return null; + } - AccountTransfer info = account.toDataTransferObject(); + final AccountTransfer info = account.toDataTransferObject(); info.setLastLogin(account.getLastLoginTime().getTime()); info.setId(account.getId()); - boolean isAdmin = isAdministrator(email); + final boolean isAdmin = isAdministrator(email); info.setAdmin(isAdmin); info.setSessionId(SessionHandler.createSessionForUser(email, transfer.getSessionId())); return info; } + /** + * See if the given sessionKey is still authenticated with the system. + * + * @param sessionKey + * unique session identifier + * @return True if sessionKey is still authenticated (active) to the system. + */ + public static boolean isAuthenticated(final String sessionKey) { + return SessionHandler.isValidSession(sessionKey); + } + /** * De-authenticate the given sessionKey. The user is logged out from the system. * - * @param sessionKey unique session identifier + * @param sessionKey + * unique session identifier */ - public void invalidate(String sessionKey) { + public void invalidate(final String sessionKey) { SessionHandler.invalidateSession(sessionKey); } @@ -429,15 +535,24 @@ public void invalidate(String sessionKey) { * * @param accountPreferences */ - public void saveAccountPreferences(AccountPreferences accountPreferences) { + public void saveAccountPreferences(final AccountPreferences accountPreferences) { accountPreferencesDAO.create(accountPreferences); } - public ArrayList getMatchingAccounts(String userId, String query, int limit) { - Set matches = dao.getMatchingAccounts(query, limit); - ArrayList result = new ArrayList<>(); - for (Account match : matches) { - AccountTransfer info = new AccountTransfer(); + /** + * @param userId + * @param query + * @param limit + * @return accounts matching the query + */ + public List getMatchingAccounts(final String userId, final String query, + final int limit) { + // TODO account object is never used? + getByEmail(userId); + final Set matches = dao.getMatchingAccounts(query, limit); + final ArrayList result = new ArrayList<>(); + for (final Account match : matches) { + final AccountTransfer info = new AccountTransfer(); info.setEmail(match.getEmail()); info.setFirstName(match.getFirstName()); info.setLastName(match.getLastName()); @@ -446,43 +561,61 @@ public ArrayList getMatchingAccounts(String userId, String quer return result; } - public AccountResults retrieveAccounts(String userId, int start, int limit, String sort, boolean asc) { + /** + * @param userId + * @param start + * @param limit + * @param sort + * @param asc + * @return window of results to all accounts + */ + public AccountResults retrieveAccounts(final String userId, final int start, final int limit, + final String sort, final boolean asc) { if (!isAdministrator(userId)) { - Logger.warn(userId + " attempting to retrieve all user accounts without admin privileges"); + Logger.warn(userId + + " attempting to retrieve all user accounts without admin privileges"); return null; } - AccountResults results = new AccountResults(); - EntryController entryController = new EntryController(); - List accounts = dao.getAccounts(start, limit, sort, asc); + final AccountResults results = new AccountResults(); + final EntryController entryController = new EntryController(); + final List accounts = dao.getAccounts(start, limit, sort, asc); - ArrayList infos = new ArrayList<>(); - for (Account userAccount : accounts) { - AccountTransfer info = userAccount.toDataTransferObject(); - long count = entryController.getNumberOfOwnerEntries(userId, userAccount.getEmail()); + final List infos = new ArrayList<>(); + for (final Account userAccount : accounts) { + final AccountTransfer info = userAccount.toDataTransferObject(); + final long count = entryController.getNumberOfOwnerEntries(userId, + userAccount.getEmail()); info.setUserEntryCount(count); info.setAdmin(isAdministrator(userAccount.getEmail())); infos.add(info); } results.getResults().addAll(infos); - long count = dao.getAccountsCount(); + final long count = dao.getAccountsCount(); results.setResultCount(count); return results; } - public void removeMemberFromGroup(long id, String email) throws ControllerException { - Account account = getByEmail(email); - if (account == null) + /** + * @param id + * @param email + * @throws ControllerException + */ + public void removeMemberFromGroup(final long id, final String email) throws ControllerException { + final Account account = getByEmail(email); + if (account == null) { throw new ControllerException("Could not find account " + email); + } - Group group = DAOFactory.getGroupDAO().get(id); - if (group == null) + final Group group = DAOFactory.getGroupDAO().get(id); + if (group == null) { throw new ControllerException("Could not find group " + id); + } account.getGroups().remove(group); try { dao.update(account); - } catch (DAOException e) { + } catch (final DAOException e) { throw new ControllerException(e); } } diff --git a/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java b/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java index 666b15c87..6de1c7ea4 100755 --- a/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java +++ b/src/main/java/org/jbei/ice/lib/dto/ConfigurationKey.java @@ -34,7 +34,9 @@ public enum ConfigurationKey implements IDataTransferModel { PASSWORD_CHANGE_ALLOWED("YES"), PROFILE_EDIT_ALLOWED("YES"), JOIN_WEB_OF_REGISTRIES("NO"), - WEB_OF_REGISTRIES_MASTER("registry.jbei.org"); + WEB_OF_REGISTRIES_MASTER("registry.jbei.org"), + + AUTHENTICATION_BACKEND("org.jbei.ice.lib.account.authentication.LocalAuthentication"); private String defaultValue; diff --git a/src/main/java/org/jbei/ice/services/rest/UserResource.java b/src/main/java/org/jbei/ice/services/rest/UserResource.java index 5ad91f815..05faa8861 100644 --- a/src/main/java/org/jbei/ice/services/rest/UserResource.java +++ b/src/main/java/org/jbei/ice/services/rest/UserResource.java @@ -79,7 +79,7 @@ public AccountResults get(@DefaultValue("0") @QueryParam("offset") final int off @GET @Produces(MediaType.APPLICATION_JSON) @Path("/autocomplete") - public ArrayList getAutoCompleteForAvailableAccounts( + public List getAutoCompleteForAvailableAccounts( @QueryParam("val") final String val, @DefaultValue("8") @QueryParam("limit") final int limit) { final String userId = getUserId(); From acaa2dfcbc3ef6618e24a0b3aaa09a011ab35bef Mon Sep 17 00:00:00 2001 From: William Morrell Date: Thu, 16 Apr 2015 17:32:56 -0700 Subject: [PATCH 33/67] Was using relative path to build HMAC signature, need to use absolute URI path --- .../jbei/ice/services/rest/AuthenticationInterceptor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java index 32b2415ed..3dc3e4174 100644 --- a/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java +++ b/src/main/java/org/jbei/ice/services/rest/AuthenticationInterceptor.java @@ -115,10 +115,13 @@ public void filter(final ContainerRequestContext requestContext) throws IOExcept } else { final UriInfo uriInfo = requestContext.getUriInfo(); final MultivaluedMap params = uriInfo.getQueryParameters(false); - final HmacSignature sig = AUTHORIZOR.initSignature(hmac, requestContext.getMethod(), - requestContext.getHeaderString("Host"), uriInfo.getPath(), params); + final String method = requestContext.getMethod(); + final String host = requestContext.getHeaderString("Host"); + final String path = uriInfo.getAbsolutePath().getPath(); // uriInfo path is relative + final HmacSignature sig = AUTHORIZOR.initSignature(hmac, method, host, path, params); requestContext.setProperty(HMAC_SIGNATURE, sig); requestContext.setProperty(EXPECTED_SIGNATURE, parts[3]); + } } From e90a91700b49be67de13f7cc1704a69e1c58ec4d Mon Sep 17 00:00:00 2001 From: William Morrell Date: Mon, 22 Jun 2015 16:36:29 -0700 Subject: [PATCH 34/67] Fixing merge conflicts to merge into dev --- .../org/jbei/ice/lib/account/AccountController.java | 2 +- .../jbei/ice/services/rest/AccessTokenResource.java | 2 +- .../jbei/ice/services/rest/BulkUploadResource.java | 5 ++--- .../org/jbei/ice/services/rest/FileResource.java | 6 ++++-- .../org/jbei/ice/services/rest/PartResource.java | 7 ++++--- .../org/jbei/ice/services/rest/RestResource.java | 12 ++++++++++++ .../java/org/jbei/ice/services/rest/WebResource.java | 3 +++ 7 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/account/AccountController.java b/src/main/java/org/jbei/ice/lib/account/AccountController.java index c352ea1c2..4916863c3 100755 --- a/src/main/java/org/jbei/ice/lib/account/AccountController.java +++ b/src/main/java/org/jbei/ice/lib/account/AccountController.java @@ -344,7 +344,7 @@ public long getAccountId(final String email) { * @param sessionKey * @return Account object matching a session key, or {@code null} */ - public Account getAccountBySessionKey(final String sessionKey) { + public AccountTransfer getAccountBySessionKey(final String sessionKey) { final String userId = SessionHandler.getUserIdBySession(sessionKey); if (userId == null) { Logger.warn("Could not retrieve user id for session " + sessionKey); diff --git a/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java b/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java index 01f993033..57c2aa6e8 100644 --- a/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java +++ b/src/main/java/org/jbei/ice/services/rest/AccessTokenResource.java @@ -45,7 +45,7 @@ public Response create(final AccountTransfer transfer) { * Invalidates the current session information. */ @DELETE - public void deleteToken() { + public void deleteToken(@HeaderParam(AUTHENTICATION_PARAM_NAME) String sessionId) { // ensure the user is valid getUserId(); accountController.invalidate(sessionId); diff --git a/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java b/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java index 87e64c6ef..1c7b14660 100644 --- a/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java +++ b/src/main/java/org/jbei/ice/services/rest/BulkUploadResource.java @@ -88,9 +88,8 @@ public BulkUploadInfo read(@Context final UriInfo info, @PathParam("id") final l public Response getPartNumbersForUpload( @QueryParam("type") EntryType uploadType, @QueryParam("token") String token, - @DefaultValue("8") @QueryParam("limit") int limit, - @HeaderParam("X-ICE-Authentication-SessionId") String sessionId) { - String userId = getUserIdFromSessionHeader(sessionId); + @DefaultValue("8") @QueryParam("limit") int limit) { + String userId = getUserId(); ArrayList results = controller.getMatchingPartNumbersForLinks(uploadType, token, limit); return super.respond(results); } diff --git a/src/main/java/org/jbei/ice/services/rest/FileResource.java b/src/main/java/org/jbei/ice/services/rest/FileResource.java index cd527118b..c123104fd 100644 --- a/src/main/java/org/jbei/ice/services/rest/FileResource.java +++ b/src/main/java/org/jbei/ice/services/rest/FileResource.java @@ -43,6 +43,7 @@ import org.jbei.ice.lib.entry.sequence.composers.pigeon.PigeonSBOLv; import org.jbei.ice.lib.models.Sequence; import org.jbei.ice.lib.models.TraceSequence; +import org.jbei.ice.lib.net.RemoteAccessController; import org.jbei.ice.lib.net.RemoteEntries; import org.jbei.ice.lib.utils.EntriesAsCSV; import org.jbei.ice.lib.utils.Utils; @@ -141,8 +142,9 @@ public Response getAttachment(@PathParam("fileId") final String fileId) { public Response getRemoteAttachment(@PathParam("id") final long partnerId, @PathParam("fileId") final String fileId) { try { - final RemoteAccessController controller = new RemoteAccessController(); - final File file = controller.getPublicAttachment(partnerId, fileId); + final RemoteEntries entries = new RemoteEntries(); + final String userId = getUserId(); + final File file = entries.getPublicAttachment(userId, partnerId, fileId); if (file == null) { return respond(Response.Status.NOT_FOUND); } diff --git a/src/main/java/org/jbei/ice/services/rest/PartResource.java b/src/main/java/org/jbei/ice/services/rest/PartResource.java index 7bfd27087..ca1f28df2 100644 --- a/src/main/java/org/jbei/ice/services/rest/PartResource.java +++ b/src/main/java/org/jbei/ice/services/rest/PartResource.java @@ -6,6 +6,7 @@ import java.lang.reflect.Type; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.List; import java.util.Set; import javax.ws.rs.Consumes; @@ -43,6 +44,7 @@ import org.jbei.ice.lib.dto.entry.PartData; import org.jbei.ice.lib.dto.entry.PartStatistics; import org.jbei.ice.lib.dto.entry.TraceSequenceAnalysis; +import org.jbei.ice.lib.dto.entry.Visibility; import org.jbei.ice.lib.dto.permission.AccessPermission; import org.jbei.ice.lib.dto.sample.PartSample; import org.jbei.ice.lib.entry.Entries; @@ -662,10 +664,9 @@ public Response deleteLink(@PathParam("id") final long partId, @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) - public Response updateEntries(@HeaderParam(value = "X-ICE-Authentication-SessionId") String sessionId, - @QueryParam(value = "visibility") Visibility visibility, + public Response updateEntries(@QueryParam(value = "visibility") Visibility visibility, List entryIds) { - String userId = getUserIdFromSessionHeader(sessionId); + String userId = getUserId(); log(userId, "updating visibility of " + entryIds.size() + " entries to " + visibility); Entries entries = new Entries(); List arrayList = new ArrayList<>(); diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index db18bccfc..fb9471046 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -1,14 +1,26 @@ package org.jbei.ice.services.rest; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.nio.file.Paths; +import java.security.Key; + import javax.servlet.http.HttpServletRequest; import javax.ws.rs.HeaderParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; +import org.jbei.auth.KeyTable; +import org.jbei.auth.hmac.HmacAuthorizor; import org.jbei.auth.hmac.HmacSignature; +import org.jbei.auth.hmac.HmacSignatureFactory; import org.jbei.ice.lib.account.SessionHandler; import org.jbei.ice.lib.common.logging.Logger; +import org.jbei.ice.lib.dao.hibernate.HibernateUtil; +import org.jbei.ice.lib.dto.ConfigurationKey; +import org.jbei.ice.lib.utils.Utils; /** * Parent class for all rest resource objects diff --git a/src/main/java/org/jbei/ice/services/rest/WebResource.java b/src/main/java/org/jbei/ice/services/rest/WebResource.java index 447f41e7b..53a21b0e5 100644 --- a/src/main/java/org/jbei/ice/services/rest/WebResource.java +++ b/src/main/java/org/jbei/ice/services/rest/WebResource.java @@ -1,10 +1,12 @@ package org.jbei.ice.services.rest; import java.util.ArrayList; +import java.util.List; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; @@ -17,6 +19,7 @@ import javax.ws.rs.core.UriInfo; import org.hsqldb.lib.StringUtil; + import org.jbei.ice.lib.dto.entry.AttachmentInfo; import org.jbei.ice.lib.dto.entry.PartData; import org.jbei.ice.lib.dto.entry.PartStatistics; From de518f2dea8149ef254d4e9f597994090c946c4b Mon Sep 17 00:00:00 2001 From: William Morrell Date: Mon, 22 Jun 2015 17:11:00 -0700 Subject: [PATCH 35/67] Picked the wrong things to merge and project was not compiling --- .../org/jbei/ice/services/rest/RemoteAccessResource.java | 8 +++----- .../java/org/jbei/ice/services/rest/SampleResource.java | 8 -------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java index dc98dad09..4333b24b4 100644 --- a/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RemoteAccessResource.java @@ -84,7 +84,7 @@ public Response getSequence(@PathParam("id") final long remoteId, public Response getSequenceTraces(@PathParam("id") long remoteId, @PathParam("entryId") long partId) { List traces = controller.getRemoteTraces(remoteId, partId); - if (traces == null) + if (traces == null) { return Response.status(Response.Status.NO_CONTENT).build(); } return Response.status(Response.Status.OK).entity(traces).build(); @@ -120,8 +120,7 @@ public FolderDetails getPublicFolderEntries(@PathParam("id") final long remoteId @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{partId}/samples") public Response getRemotePartSamples(@PathParam("id") long remoteId, - @PathParam("partId") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + @PathParam("partId") long partId) { List result = controller.getRemotePartSamples(remoteId, partId); return super.respond(result); } @@ -135,8 +134,7 @@ public Response getRemotePartSamples(@PathParam("id") long remoteId, @Produces(MediaType.APPLICATION_JSON) @Path("/parts/{partId}/comments") public Response getRemotePartComments(@PathParam("id") long remoteId, - @PathParam("partId") long partId, - @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { + @PathParam("partId") long partId) { List result = controller.getRemotePartComments(remoteId, partId); return super.respond(result); } diff --git a/src/main/java/org/jbei/ice/services/rest/SampleResource.java b/src/main/java/org/jbei/ice/services/rest/SampleResource.java index d7be5ef97..1b3bfdf2e 100644 --- a/src/main/java/org/jbei/ice/services/rest/SampleResource.java +++ b/src/main/java/org/jbei/ice/services/rest/SampleResource.java @@ -73,14 +73,6 @@ public Response getRequests(@DefaultValue("0") @QueryParam("offset") final int o @QueryParam("status") final SampleRequestStatus status) { final String userId = getUserId(); Logger.info(userId + ": retrieving sample requests"); - SampleRequestStatus requestStatus = null; - if (!StringUtils.isEmpty(status)) { - try { - requestStatus = SampleRequestStatus.valueOf(status); - } catch (Exception e) { - requestStatus = null; - } - } final UserSamples samples = requestRetriever.getRequests(userId, offset, limit, sort, asc, status, filter); return super.respond(Response.Status.OK, samples); From 96293aade18b7b914a397befb88ca447fa2ccb1a Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Thu, 25 Jun 2015 12:18:07 -0700 Subject: [PATCH 36/67] fix for #20 --- src/main/webapp/scripts/profile/profileController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/scripts/profile/profileController.js b/src/main/webapp/scripts/profile/profileController.js index d3e3fe997..3700bdeb6 100644 --- a/src/main/webapp/scripts/profile/profileController.js +++ b/src/main/webapp/scripts/profile/profileController.js @@ -61,7 +61,7 @@ angular.module('ice.profile.controller', []) // get settings Settings().getSetting({key: 'PASSWORD_CHANGE_ALLOWED'}, function (result) { - $scope.passwordChangeAllowed = (result.value == 'yes'); + $scope.passwordChangeAllowed = (result.value.toLowerCase() === 'yes'); }); $scope.preferenceEntryDefaults = [ From 47f06190a24fbcabdc29ce2eac371a3c99e9bca7 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Mon, 29 Jun 2015 13:58:51 -0700 Subject: [PATCH 37/67] using relative paths --- src/main/webapp/scripts/admin/adminController.js | 2 +- .../webapp/scripts/collection/collectionController.js | 8 ++++---- src/main/webapp/scripts/entry/entryController.js | 2 +- src/main/webapp/scripts/profile/profileController.js | 2 +- src/main/webapp/scripts/search/searchController.js | 2 +- src/main/webapp/scripts/wor/worController.js | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/webapp/scripts/admin/adminController.js b/src/main/webapp/scripts/admin/adminController.js index f8e9f3758..3bed74903 100644 --- a/src/main/webapp/scripts/admin/adminController.js +++ b/src/main/webapp/scripts/admin/adminController.js @@ -209,7 +209,7 @@ angular.module('ice.admin.controller', []) $location.path("entry/" + entry.id); }; - $scope.tranferredPopupTooltip = "/scripts/admin/transferred-tooltip.html"; + $scope.tranferredPopupTooltip = "scripts/admin/transferred-tooltip.html"; $scope.transferredTooltip = function (entry) { $scope.tooltip = undefined; diff --git a/src/main/webapp/scripts/collection/collectionController.js b/src/main/webapp/scripts/collection/collectionController.js index d954c675b..050c936c7 100644 --- a/src/main/webapp/scripts/collection/collectionController.js +++ b/src/main/webapp/scripts/collection/collectionController.js @@ -253,7 +253,7 @@ angular.module('ice.collection.controller', []) function (result) { callback(result.entries[0].id); }); - }, $scope.params.count, offset, "/folders/" + $scope.params.folderId, $scope.params.sort); + }, $scope.params.count, offset, "folders/" + $scope.params.folderId, $scope.params.sort); $location.path("entry/" + entry.id); }; @@ -268,7 +268,7 @@ angular.module('ice.collection.controller', []) }); }; - $scope.folderPopupTemplateUrl = "/views/folder/template.html"; + $scope.folderPopupTemplateUrl = "views/folder/template.html"; // opens a modal that presents user with options to share selected folder $scope.openFolderShareSettings = function () { @@ -352,7 +352,7 @@ angular.module('ice.collection.controller', []) // also the main controller .controller('CollectionController', function ($scope, $state, $filter, $location, $cookieStore, $rootScope, Folders, Settings, Search, Samples) { // todo : set on all - var searchUrl = "/search"; + var searchUrl = "search"; if ($location.path().slice(0, searchUrl.length) != searchUrl) { $location.search('q', null); } @@ -489,7 +489,7 @@ angular.module('ice.collection.controller', []) }) }; - $scope.shoppingCartTemplate = "/views/shopping-cart-template.html"; + $scope.shoppingCartTemplate = "views/shopping-cart-template.html"; // remove sample request $scope.removeFromCart = function (content, entry) { diff --git a/src/main/webapp/scripts/entry/entryController.js b/src/main/webapp/scripts/entry/entryController.js index 9bbe25858..95c38d536 100644 --- a/src/main/webapp/scripts/entry/entryController.js +++ b/src/main/webapp/scripts/entry/entryController.js @@ -206,7 +206,7 @@ angular.module('ice.entry.controller', []) }; $scope.format = "M/d/yyyy h:mm a"; - $scope.newSampleTemplate = "/scripts/entry/sample/barcode-popover.html"; + $scope.newSampleTemplate = "scripts/entry/sample/barcode-popover.html"; $scope.enablePopup = function (row, col) { console.log("enable", row, col); console.log($scope.newSample.open.cell === row + (10 + col + '').slice(-2)); diff --git a/src/main/webapp/scripts/profile/profileController.js b/src/main/webapp/scripts/profile/profileController.js index 229a609a6..43c36cc92 100644 --- a/src/main/webapp/scripts/profile/profileController.js +++ b/src/main/webapp/scripts/profile/profileController.js @@ -27,7 +27,7 @@ angular.module('ice.profile.controller', []) }); }; - $scope.profileEntryPopupTemplate = "/views/folder/template.html"; + $scope.profileEntryPopupTemplate = "views/folder/template.html"; $scope.tooltipDetails = function (entry) { $scope.currentTooltip = undefined; diff --git a/src/main/webapp/scripts/search/searchController.js b/src/main/webapp/scripts/search/searchController.js index bc7697fa5..eb87f6916 100644 --- a/src/main/webapp/scripts/search/searchController.js +++ b/src/main/webapp/scripts/search/searchController.js @@ -71,7 +71,7 @@ angular.module('ice.search.controller', []) return 'info'; }; - $scope.searchResultPopupTemplate = "/scripts/search/tooltip.html"; + $scope.searchResultPopupTemplate = "scripts/search/tooltip.html"; $scope.tooltipDetails = function (entry) { $scope.searchResultToolTip = undefined; diff --git a/src/main/webapp/scripts/wor/worController.js b/src/main/webapp/scripts/wor/worController.js index 0cee72d84..29c6141ab 100644 --- a/src/main/webapp/scripts/wor/worController.js +++ b/src/main/webapp/scripts/wor/worController.js @@ -237,7 +237,7 @@ angular.module('ice.wor.controller', []) $scope.selectRemotePartnerFolder = function (folder) { $scope.partnerId = $stateParams.partner; - $location.path('/web/' + $stateParams.partner + "/folder/" + folder.id); + $location.path('web/' + $stateParams.partner + "/folder/" + folder.id); }; }) .controller('WebOfRegistriesController', function ($rootScope, $scope, $location, $modal, $cookieStore, $stateParams, WebOfRegistries, Remote, Settings) { From 57e89a6784485b7cef2113fd93db9fcf0d56339a Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Mon, 29 Jun 2015 16:20:09 -0700 Subject: [PATCH 38/67] check for valid text in truncate filter --- src/main/webapp/scripts/filters.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/webapp/scripts/filters.js b/src/main/webapp/scripts/filters.js index 5e7f7e759..35b1e3071 100755 --- a/src/main/webapp/scripts/filters.js +++ b/src/main/webapp/scripts/filters.js @@ -21,6 +21,9 @@ iceFilters.filter('capitalize', function () { iceFilters.filter('truncate', function () { return function (text, length, end) { + if (!text) + return; + if (isNaN(length)) length = 10; From de5900d15c0e9672dcdeb6f5e1ec3a43c3554573 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Mon, 29 Jun 2015 16:20:27 -0700 Subject: [PATCH 39/67] upgrade csv parser --- pom.xml | 4 ++-- src/main/java/org/jbei/ice/lib/bulkupload/BulkCSVUpload.java | 2 +- src/main/java/org/jbei/ice/lib/utils/EntriesAsCSV.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 3f4cd2e97..ecfcb94bf 100755 --- a/pom.xml +++ b/pom.xml @@ -108,9 +108,9 @@ 1.3.1 - net.sf.opencsv + com.opencsv opencsv - 2.3 + 3.4 ch.qos.logback diff --git a/src/main/java/org/jbei/ice/lib/bulkupload/BulkCSVUpload.java b/src/main/java/org/jbei/ice/lib/bulkupload/BulkCSVUpload.java index fabc0cfe5..4366d1efc 100644 --- a/src/main/java/org/jbei/ice/lib/bulkupload/BulkCSVUpload.java +++ b/src/main/java/org/jbei/ice/lib/bulkupload/BulkCSVUpload.java @@ -1,6 +1,6 @@ package org.jbei.ice.lib.bulkupload; -import au.com.bytecode.opencsv.CSVParser; +import com.opencsv.CSVParser; import org.apache.commons.io.IOUtils; import org.apache.commons.io.LineIterator; import org.apache.commons.lang.StringUtils; diff --git a/src/main/java/org/jbei/ice/lib/utils/EntriesAsCSV.java b/src/main/java/org/jbei/ice/lib/utils/EntriesAsCSV.java index 7e38d778c..2edbc8a9f 100644 --- a/src/main/java/org/jbei/ice/lib/utils/EntriesAsCSV.java +++ b/src/main/java/org/jbei/ice/lib/utils/EntriesAsCSV.java @@ -1,6 +1,6 @@ package org.jbei.ice.lib.utils; -import au.com.bytecode.opencsv.CSVWriter; +import com.opencsv.CSVWriter; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.bulkupload.BulkCSVUploadHeaders; import org.jbei.ice.lib.common.logging.Logger; From 1b3b58a29a5d01309869087c487a924c88958ef3 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Mon, 29 Jun 2015 17:42:31 -0700 Subject: [PATCH 40/67] cleanup: removing controllerException --- .../org/jbei/ice/ControllerException.java | 44 -------- .../ice/lib/account/AccountController.java | 73 +++++------- .../jbei/ice/lib/account/AccountUtils.java | 15 +-- .../lib/account/PreferencesController.java | 39 ++----- .../lib/bulkupload/BulkUploadController.java | 3 +- .../jbei/ice/lib/common/logging/Logger.java | 12 +- .../attachment/AttachmentController.java | 20 +--- .../sequence/SequenceAnalysisController.java | 62 +++++------ .../entry/sequence/SequenceController.java | 11 +- .../jbei/ice/lib/group/GroupController.java | 12 +- .../ice/lib/message/MessageController.java | 46 +++----- .../jbei/ice/services/rest/RestResource.java | 104 ++++++------------ .../rest/multipart/IceApplication.java | 12 +- 13 files changed, 145 insertions(+), 308 deletions(-) delete mode 100755 src/main/java/org/jbei/ice/ControllerException.java diff --git a/src/main/java/org/jbei/ice/ControllerException.java b/src/main/java/org/jbei/ice/ControllerException.java deleted file mode 100755 index 2e76b80b9..000000000 --- a/src/main/java/org/jbei/ice/ControllerException.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.jbei.ice; - -/** - * Exception class for controllers. - * - * @author Zinovii Dmytriv - */ -public class ControllerException extends Exception { - private static final long serialVersionUID = -4198825232452614310L; - - /** - * Base constructor. - */ - public ControllerException() { - } - - /** - * Create a new ControllerException with a message. - * - * @param message - */ - public ControllerException(String message) { - super(message); - } - - /** - * Create a new ControllerException with a {@link Throwable}. - * - * @param cause - */ - public ControllerException(Throwable cause) { - super(cause); - } - - /** - * Create a new ControllerException with a message and a {@link Throwable}. - * - * @param message - * @param cause - */ - public ControllerException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/org/jbei/ice/lib/account/AccountController.java b/src/main/java/org/jbei/ice/lib/account/AccountController.java index 6565042a7..07fbe1a78 100755 --- a/src/main/java/org/jbei/ice/lib/account/AccountController.java +++ b/src/main/java/org/jbei/ice/lib/account/AccountController.java @@ -1,14 +1,13 @@ package org.jbei.ice.lib.account; import org.apache.commons.lang3.StringUtils; -import org.jbei.ice.ControllerException; import org.jbei.ice.lib.account.authentication.AuthenticationException; import org.jbei.ice.lib.account.authentication.IAuthentication; import org.jbei.ice.lib.account.authentication.LocalAuthentication; +import org.jbei.ice.lib.account.authentication.UserIdAuthentication; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.account.model.AccountPreferences; import org.jbei.ice.lib.common.logging.Logger; -import org.jbei.ice.lib.dao.DAOException; import org.jbei.ice.lib.dao.DAOFactory; import org.jbei.ice.lib.dao.hibernate.AccountDAO; import org.jbei.ice.lib.dao.hibernate.AccountPreferencesDAO; @@ -24,7 +23,7 @@ /** * ABI to manipulate {@link Account} objects. - *

+ *

* This class contains methods that wrap {@link org.jbei.ice.lib.dao.hibernate.AccountDAO} to * manipulate {@link Account} objects. * @@ -53,7 +52,7 @@ public AccountController() { * @return updated account object */ public AccountTransfer updateAccount(final String requester, final long userId, - final AccountTransfer transfer) { + final AccountTransfer transfer) { final Account account = dao.get(userId); if (!account.getEmail().equalsIgnoreCase(requester) && !isAdministrator(requester)) { return null; @@ -82,8 +81,7 @@ public AccountTransfer updateAccount(final String requester, final long userId, /** * Retrieve account from the database by database id. * - * @param id - * Database id of account + * @param id Database id of account * @return Account for the id */ public Account get(final long id) { @@ -93,10 +91,9 @@ public Account get(final long id) { /** * Reset a user's password * - * @param targetEmail - * email address of user account to be changed + * @param targetEmail email address of user account to be changed * @return true if the user account is found with email specified in the parameter and password - * for it is successfully reset, false otherwise + * for it is successfully reset, false otherwise */ public boolean resetPassword(final String targetEmail) { Account account = getByEmail(targetEmail); @@ -181,8 +178,7 @@ public AccountTransfer updatePassword(final String userId, final AccountTransfer * validates the account dto to ensure that the fields required (especially by the database) are * present * - * @param accountTransfer - * account dto for validation + * @param accountTransfer account dto for validation */ private boolean validateRequiredAccountFields(final AccountTransfer accountTransfer) { if (accountTransfer.getFirstName() == null @@ -205,10 +201,8 @@ private boolean validateRequiredAccountFields(final AccountTransfer accountTrans * Creates a new account using the parameters passed. A random password is initially generated , * encrypted and assigned to the account * - * @param info - * contains information needed to create account - * @param sendEmail - * whether to send account information (including password by email) + * @param info contains information needed to create account + * @param sendEmail whether to send account information (including password by email) * @return generated password */ public AccountTransfer createNewAccount(final AccountTransfer info, final boolean sendEmail) { @@ -310,8 +304,7 @@ public Account createAdminAccount() { /** * Retrieve {@link Account} by user id. * - * @param email - * unique identifier for account, typically email + * @param email unique identifier for account, typically email * @return {@link Account} */ public Account getByEmail(final String email) { @@ -319,11 +312,9 @@ public Account getByEmail(final String email) { } /** - * @param email - * an account identifier (usually email) + * @param email an account identifier (usually email) * @return database identifier of account matching account identifier (email) - * @throws IllegalArgumentException - * for an invalid account identifier + * @throws IllegalArgumentException for an invalid account identifier */ public long getAccountId(final String email) { final Account account = dao.getByEmail(email); @@ -378,8 +369,7 @@ public boolean isAdministrator(final Account account) { /** * Check in the database if an account is a moderator. * - * @param userId - * unique account identifier for user + * @param userId unique account identifier for user * @return True, if the account is a moderator. */ public boolean isAdministrator(final String userId) { @@ -393,18 +383,17 @@ public boolean isAdministrator(final String userId) { /** * Authenticate a user in the database. - *

+ *

* Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the * settings file, authenticate the user, and return the sessionData * * @param login * @param password - * @param ip - * IP Address of the user. + * @param ip IP Address of the user. * @return the account identifier (email) on a successful login, otherwise {@code null} */ public String authenticate(final String login, final String password, final String ip) { - final IAuthentication authentication = getAuthenticationBackend(); + final IAuthentication authentication = new UserIdAuthentication(); String email; try { @@ -472,13 +461,12 @@ public IAuthentication getAuthenticationBackend() { /** * Authenticate a user in the database. - *

+ *

* Using the {@link org.jbei.ice.lib.account.authentication.IAuthentication} specified in the * settings file, authenticate the user, and return the sessionData * - * @param transfer - * user information containing the email and password to be used for authentication - * If the sessionId field is set, it may or may not be used as the user's session id + * @param transfer user information containing the email and password to be used for authentication + * If the sessionId field is set, it may or may not be used as the user's session id * @return {@link AccountTransfer} */ public AccountTransfer authenticate(final AccountTransfer transfer) { @@ -505,8 +493,7 @@ public AccountTransfer authenticate(final AccountTransfer transfer) { /** * See if the given sessionKey is still authenticated with the system. * - * @param sessionKey - * unique session identifier + * @param sessionKey unique session identifier * @return True if sessionKey is still authenticated (active) to the system. */ public static boolean isAuthenticated(final String sessionKey) { @@ -516,8 +503,7 @@ public static boolean isAuthenticated(final String sessionKey) { /** * De-authenticate the given sessionKey. The user is logged out from the system. * - * @param sessionKey - * unique session identifier + * @param sessionKey unique session identifier */ public void invalidate(final String sessionKey) { SessionHandler.invalidateSession(sessionKey); @@ -539,7 +525,7 @@ public void saveAccountPreferences(final AccountPreferences accountPreferences) * @return accounts matching the query */ public List getMatchingAccounts(final String userId, final String query, - final int limit) { + final int limit) { // TODO account object is never used? getByEmail(userId); final Set matches = dao.getMatchingAccounts(query, limit); @@ -563,7 +549,7 @@ public List getMatchingAccounts(final String userId, final Stri * @return window of results to all accounts */ public AccountResults retrieveAccounts(final String userId, final int start, final int limit, - final String sort, final boolean asc) { + final String sort, final boolean asc) { if (!isAdministrator(userId)) { Logger.warn(userId + " attempting to retrieve all user accounts without admin privileges"); @@ -593,23 +579,18 @@ public AccountResults retrieveAccounts(final String userId, final int start, fin /** * @param id * @param email - * @throws ControllerException */ - public void removeMemberFromGroup(final long id, final String email) throws ControllerException { + public void removeMemberFromGroup(final long id, final String email) { final Account account = getByEmail(email); if (account == null) { - throw new ControllerException("Could not find account " + email); + throw new IllegalArgumentException("Could not find account " + email); } final Group group = DAOFactory.getGroupDAO().get(id); if (group == null) { - throw new ControllerException("Could not find group " + id); + throw new IllegalArgumentException("Could not find group " + id); } account.getGroups().remove(group); - try { - dao.update(account); - } catch (final DAOException e) { - throw new ControllerException(e); - } + dao.update(account); } } diff --git a/src/main/java/org/jbei/ice/lib/account/AccountUtils.java b/src/main/java/org/jbei/ice/lib/account/AccountUtils.java index 3fa9e1bcf..42bd7a331 100755 --- a/src/main/java/org/jbei/ice/lib/account/AccountUtils.java +++ b/src/main/java/org/jbei/ice/lib/account/AccountUtils.java @@ -1,15 +1,16 @@ package org.jbei.ice.lib.account; -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.KeySpec; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.PBEKeySpec; - +import org.apache.commons.lang3.StringUtils; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.utils.Utils; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; + /** * Utility class for account management * @@ -30,7 +31,7 @@ public static String encryptPassword(String password, String userSalt) { } public static String encryptNewUserPassword(String password, String salt) { - if (password == null || password.trim().isEmpty() || salt == null || salt.trim().isEmpty()) + if (StringUtils.isEmpty(password) || StringUtils.isEmpty(salt)) throw new IllegalArgumentException("Password and salt cannot be empty"); KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 20000, 160); diff --git a/src/main/java/org/jbei/ice/lib/account/PreferencesController.java b/src/main/java/org/jbei/ice/lib/account/PreferencesController.java index c3658e1cd..291a8c937 100644 --- a/src/main/java/org/jbei/ice/lib/account/PreferencesController.java +++ b/src/main/java/org/jbei/ice/lib/account/PreferencesController.java @@ -1,14 +1,7 @@ package org.jbei.ice.lib.account; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -import org.jbei.ice.ControllerException; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.account.model.Preference; -import org.jbei.ice.lib.dao.DAOException; import org.jbei.ice.lib.dao.DAOFactory; import org.jbei.ice.lib.dao.hibernate.AccountDAO; import org.jbei.ice.lib.dao.hibernate.PreferencesDAO; @@ -17,6 +10,11 @@ import org.jbei.ice.lib.dto.user.PreferenceKey; import org.jbei.ice.lib.dto.user.UserPreferences; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + /** * Controller for managing user preferences. * @@ -32,15 +30,9 @@ public PreferencesController() { accountDAO = DAOFactory.getAccountDAO(); } - public HashMap retrieveAccountPreferences(Account account, ArrayList keys) - throws ControllerException { + public HashMap retrieveAccountPreferences(Account account, ArrayList keys) { HashMap preferences = new HashMap<>(); - ArrayList results; - try { - results = dao.getAccountPreferences(account, keys); - } catch (DAOException de) { - throw new ControllerException(de); - } + ArrayList results = dao.getAccountPreferences(account, keys); for (Preference preference : results) { PreferenceKey key = PreferenceKey.fromString(preference.getKey()); @@ -101,22 +93,9 @@ public HashMap retrieveUserPreferenceList(Account account, List< return dao.retrievePreferenceValues(account, values); } - // really an update - public boolean saveSetting(Account account, String key, String value) throws ControllerException { - try { - return dao.createOrUpdatePreference(account, key, value) != null; - } catch (DAOException e) { - throw new ControllerException(e); - } - } - - public Preference createPreference(Account account, String key, String value) throws ControllerException { + public Preference createPreference(Account account, String key, String value) { Preference preference = new Preference(account, key.toUpperCase(), value); - try { - return dao.create(preference); - } catch (DAOException e) { - throw new ControllerException(e); - } + return dao.create(preference); } public PreferenceInfo updatePreference(String requesterEmail, long userId, String key, String value) { diff --git a/src/main/java/org/jbei/ice/lib/bulkupload/BulkUploadController.java b/src/main/java/org/jbei/ice/lib/bulkupload/BulkUploadController.java index b7d3b6dee..14ca7e3f9 100755 --- a/src/main/java/org/jbei/ice/lib/bulkupload/BulkUploadController.java +++ b/src/main/java/org/jbei/ice/lib/bulkupload/BulkUploadController.java @@ -2,7 +2,6 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; -import org.jbei.ice.ControllerException; import org.jbei.ice.lib.access.Permission; import org.jbei.ice.lib.access.PermissionException; import org.jbei.ice.lib.access.PermissionsController; @@ -383,7 +382,7 @@ public BulkUploadInfo submitBulkImportDraft(String userId, long draftId) throws return null; } - public boolean revertSubmitted(Account account, long uploadId) throws ControllerException { + public boolean revertSubmitted(Account account, long uploadId) { boolean isAdmin = accountController.isAdministrator(account.getEmail()); if (!isAdmin) { Logger.warn(account.getEmail() + " attempting to revert submitted bulk upload " diff --git a/src/main/java/org/jbei/ice/lib/common/logging/Logger.java b/src/main/java/org/jbei/ice/lib/common/logging/Logger.java index 425860267..78f3b44ea 100755 --- a/src/main/java/org/jbei/ice/lib/common/logging/Logger.java +++ b/src/main/java/org/jbei/ice/lib/common/logging/Logger.java @@ -1,17 +1,15 @@ package org.jbei.ice.lib.common.logging; -import java.text.SimpleDateFormat; -import java.util.Date; -import javax.mail.MessagingException; - -import org.jbei.ice.ControllerException; import org.jbei.ice.lib.dao.DAOException; import org.jbei.ice.lib.dto.ConfigurationKey; import org.jbei.ice.lib.utils.Emailer; import org.jbei.ice.lib.utils.Utils; - import org.slf4j.LoggerFactory; +import javax.mail.MessagingException; +import java.text.SimpleDateFormat; +import java.util.Date; + /** * Logger for ICE. * @@ -50,7 +48,7 @@ public static void debug(String message) { } private static void sendEmail(String message, Throwable e) { - if (e instanceof MessagingException || e instanceof ControllerException || e instanceof DAOException || true) { + if (e instanceof MessagingException || e instanceof DAOException || true) { // if error is "Can't send email", there is no need to try to send email return; } diff --git a/src/main/java/org/jbei/ice/lib/entry/attachment/AttachmentController.java b/src/main/java/org/jbei/ice/lib/entry/attachment/AttachmentController.java index f363c6996..dc250c4a3 100755 --- a/src/main/java/org/jbei/ice/lib/entry/attachment/AttachmentController.java +++ b/src/main/java/org/jbei/ice/lib/entry/attachment/AttachmentController.java @@ -1,10 +1,8 @@ package org.jbei.ice.lib.entry.attachment; import org.apache.commons.lang3.StringUtils; -import org.jbei.ice.ControllerException; import org.jbei.ice.lib.access.PermissionException; import org.jbei.ice.lib.account.model.Account; -import org.jbei.ice.lib.dao.DAOException; import org.jbei.ice.lib.dao.DAOFactory; import org.jbei.ice.lib.dao.hibernate.AttachmentDAO; import org.jbei.ice.lib.dao.hibernate.EntryDAO; @@ -45,7 +43,7 @@ public AttachmentController() { * This file identifier is assigned on upload * * @return Attachment file if one is found with the identifier, null otherwise (including if the user making - * the request does not have read permissions on the entry that this attachment is associated with) + * the request does not have read permissions on the entry that this attachment is associated with) */ public File getAttachmentByFileId(String userId, String fileId) { Attachment attachment = dao.getByFileId(fileId); @@ -76,13 +74,10 @@ public String getFileName(String userId, String fileId) { * @param attachment attachment * @param inputStream The data stream of the file. * @return Saved attachment. - * @throws ControllerException */ - public Attachment save(Account account, Attachment attachment, InputStream inputStream) throws ControllerException { - if (attachment.getEntry().getVisibility() != Visibility.TRANSFERRED.getValue() && - !entryAuthorization.canWrite(account.getEmail(), attachment.getEntry())) { - throw new ControllerException("No permissions to save attachment!"); - } + public Attachment save(Account account, Attachment attachment, InputStream inputStream) { + if (attachment.getEntry().getVisibility() != Visibility.TRANSFERRED.getValue()) + entryAuthorization.expectWrite(account.getEmail(), attachment.getEntry()); if (attachment.getFileId() == null || attachment.getFileId().isEmpty()) { String fileId = Utils.generateUUID(); @@ -94,12 +89,7 @@ public Attachment save(Account account, Attachment attachment, InputStream input String dataDir = Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY); File attachmentDir = Paths.get(dataDir, attachmentDirName).toFile(); - - try { - return dao.save(attachmentDir, attachment, inputStream); - } catch (DAOException e) { - throw new ControllerException("Failed to save attachment!", e); - } + return dao.save(attachmentDir, attachment, inputStream); } /** diff --git a/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceAnalysisController.java b/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceAnalysisController.java index d3b6af7a9..be84d5715 100755 --- a/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceAnalysisController.java +++ b/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceAnalysisController.java @@ -1,13 +1,5 @@ package org.jbei.ice.lib.entry.sequence; -import java.io.File; -import java.io.InputStream; -import java.nio.file.Paths; -import java.util.Date; -import java.util.List; - -import org.jbei.ice.ControllerException; -import org.jbei.ice.lib.access.PermissionException; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dao.DAOFactory; @@ -31,6 +23,12 @@ import org.jbei.ice.lib.utils.Utils; import org.jbei.ice.lib.vo.DNASequence; +import java.io.File; +import java.io.InputStream; +import java.nio.file.Paths; +import java.util.Date; +import java.util.List; + /** * ABI to manipulate DNA sequence trace analysis * @@ -50,7 +48,7 @@ public SequenceAnalysisController() { /** * Create a new {@link TraceSequence} record and associated with the {@link Entry} entry. - *

+ *

* Creates a database record and write the inputStream to disk. * * @param entry @@ -64,7 +62,7 @@ public SequenceAnalysisController() { * @throws ControllerException */ public TraceSequence importTraceSequence(Entry entry, String filename, String depositor, String sequence, - String uuid, Date date, InputStream inputStream) { + String uuid, Date date, InputStream inputStream) { if (entry == null) { throw new IllegalArgumentException("Failed to save trace sequence with null entry!"); } @@ -85,7 +83,7 @@ public TraceSequence importTraceSequence(Entry entry, String filename, String de /** * Create a new {@link TraceSequence} record and associated with the {@link Entry} entry. - *

+ *

* Unlike importTraceSequence this method auto generates uuid and timestamp. * * @param entry @@ -96,7 +94,7 @@ public TraceSequence importTraceSequence(Entry entry, String filename, String de * @return Saved traceSequence */ public TraceSequence uploadTraceSequence(Entry entry, String filename, String depositor, - String sequence, InputStream inputStream) { + String sequence, InputStream inputStream) { return importTraceSequence(entry, filename, depositor, sequence, Utils.generateUUID(), new Date(), inputStream); } @@ -104,13 +102,10 @@ public TraceSequence uploadTraceSequence(Entry entry, String filename, String de * Remove a {@link TraceSequence} from the database and disk. * * @param traceSequence - * @throws ControllerException - * @throws PermissionException */ - public void removeTraceSequence(Account account, TraceSequence traceSequence) throws ControllerException, - PermissionException { + public void removeTraceSequence(Account account, TraceSequence traceSequence) { if (traceSequence == null) { - throw new ControllerException("Failed to delete null Trace Sequence!"); + throw new IllegalArgumentException("Failed to delete null Trace Sequence!"); } entryAuthorization.expectWrite(account.getEmail(), traceSequence.getEntry()); @@ -124,11 +119,10 @@ public void removeTraceSequence(Account account, TraceSequence traceSequence) th * * @param entry * @return Retrieved TraceSequence - * @throws ControllerException */ - public List getTraceSequences(Entry entry) throws ControllerException { + public List getTraceSequences(Entry entry) { if (entry == null) { - throw new ControllerException("Failed to get trace sequences for null entry!"); + throw new IllegalArgumentException("Failed to get trace sequences for null entry!"); } List traces; @@ -160,7 +154,7 @@ public List getTraceSequences(Entry entry) throws ControllerExcep return traces; } - public TraceSequence getTraceSequenceByFileId(String fileId) throws ControllerException { + public TraceSequence getTraceSequenceByFileId(String fileId) { return traceDao.getByFileId(fileId); } @@ -199,11 +193,10 @@ public DNASequence parse(byte[] bytes) { * * @param traceSequence * @return {@link File} object. - * @throws ControllerException */ - public File getFile(TraceSequence traceSequence) throws ControllerException { + public File getFile(TraceSequence traceSequence) { return Paths.get(Utils.getConfigValue(ConfigurationKey.DATA_DIRECTORY), tracesDirName, - traceSequence.getFileId()).toFile(); + traceSequence.getFileId()).toFile(); } /** @@ -290,13 +283,13 @@ public void buildOrRebuildAlignment(TraceSequence traceSequence, Sequence sequen if (traceSequenceAlignment == null) { traceSequenceAlignment = new TraceSequenceAlignment(traceSequence, - maxBl2SeqResult.getScore(), strand, - queryStart, queryEnd, - subjectStart, subjectEnd, - maxBl2SeqResult.getQuerySequence(), - maxBl2SeqResult.getSubjectSequence(), - sequence.getFwdHash(), - new Date()); + maxBl2SeqResult.getScore(), strand, + queryStart, queryEnd, + subjectStart, subjectEnd, + maxBl2SeqResult.getQuerySequence(), + maxBl2SeqResult.getSubjectSequence(), + sequence.getFwdHash(), + new Date()); traceSequence.setTraceSequenceAlignment(traceSequenceAlignment); } else { @@ -323,15 +316,14 @@ public void buildOrRebuildAlignment(TraceSequence traceSequence, Sequence sequen /** * Calculate sequence alignments between the sequence associated with an {@link Entry} entry * with all the {@link TraceSequence}s associated with that entry. - *

+ *

* Calls buildOrReplaceAlignment on each TraceSequence. * * @param entry - * @throws ControllerException */ - public void rebuildAllAlignments(Entry entry) throws ControllerException { + public void rebuildAllAlignments(Entry entry) { if (entry == null) { - throw new ControllerException("Failed to rebuild alignment for null entry!"); + throw new IllegalArgumentException("Failed to rebuild alignment for null entry!"); } Sequence sequence = DAOFactory.getSequenceDAO().getByEntry(entry); diff --git a/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceController.java b/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceController.java index 71b6d97ed..1746d10f9 100755 --- a/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceController.java +++ b/src/main/java/org/jbei/ice/lib/entry/sequence/SequenceController.java @@ -3,8 +3,6 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.jbei.ice.ApplicationController; -import org.jbei.ice.ControllerException; -import org.jbei.ice.lib.access.PermissionException; import org.jbei.ice.lib.access.PermissionsController; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.common.logging.Logger; @@ -194,10 +192,8 @@ protected Sequence update(String userId, Sequence sequence) { * Delete the {@link Sequence} in the database, then rebuild the search index. * * @param sequence - * @throws ControllerException - * @throws PermissionException */ - public void delete(Account account, Sequence sequence) throws ControllerException, PermissionException { + public void delete(Account account, Sequence sequence) { authorization.expectWrite(account.getEmail(), sequence.getEntry()); String tmpDir = new ConfigurationController().getPropertyValue(ConfigurationKey.TEMPORARY_DIRECTORY); dao.deleteSequence(sequence, tmpDir); @@ -234,14 +230,13 @@ public static DNASequence parse(String sequence) { * @param sequence * @param formatter * @return Text of a formatted sequence. - * @throws ControllerException */ - public String compose(Sequence sequence, IFormatter formatter) throws ControllerException { + public String compose(Sequence sequence, IFormatter formatter) { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); try { formatter.format(sequence, byteStream); } catch (FormatterException | IOException e) { - throw new ControllerException(e); + Logger.error(e); } return byteStream.toString(); } diff --git a/src/main/java/org/jbei/ice/lib/group/GroupController.java b/src/main/java/org/jbei/ice/lib/group/GroupController.java index ba7a2190a..2a8f655e8 100755 --- a/src/main/java/org/jbei/ice/lib/group/GroupController.java +++ b/src/main/java/org/jbei/ice/lib/group/GroupController.java @@ -1,6 +1,6 @@ package org.jbei.ice.lib.group; -import org.jbei.ice.ControllerException; +import org.jbei.ice.lib.access.PermissionException; import org.jbei.ice.lib.account.AccountController; import org.jbei.ice.lib.account.AccountTransfer; import org.jbei.ice.lib.account.AccountType; @@ -177,16 +177,16 @@ public boolean updateGroup(String userId, UserGroup user) { return group != null; } - public UserGroup deleteGroup(Account account, UserGroup user) throws ControllerException { + public UserGroup deleteGroup(Account account, UserGroup user) { if (user.getType() == GroupType.PUBLIC && account.getType() != AccountType.ADMIN) { String errMsg = "Non admin " + account.getEmail() + " attempting to delete public group"; Logger.error(errMsg); - throw new ControllerException(errMsg); + throw new PermissionException(errMsg); } Group group = dao.get(user.getId()); if (group == null) { - throw new ControllerException("Could not find group to delete"); + throw new IllegalArgumentException("Could not find group to delete"); } if (group.getMembers() != null) { @@ -308,10 +308,6 @@ public ArrayList retrieveGroupMembers(String uuid, boolean incl return new ArrayList<>(result); } - public long retrieveGroupMemberCount(String uuid) throws ControllerException { - return dao.getMemberCount(uuid); - } - public AccountResults getAvailableAccounts(String userId, int offset, int limit, boolean asc, String sort) { Account account = accountController.getByEmail(userId); Set accounts = new HashSet<>(); diff --git a/src/main/java/org/jbei/ice/lib/message/MessageController.java b/src/main/java/org/jbei/ice/lib/message/MessageController.java index cd851333b..d88af552f 100644 --- a/src/main/java/org/jbei/ice/lib/message/MessageController.java +++ b/src/main/java/org/jbei/ice/lib/message/MessageController.java @@ -1,15 +1,9 @@ package org.jbei.ice.lib.message; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.jbei.ice.ControllerException; import org.jbei.ice.lib.account.AccountTransfer; import org.jbei.ice.lib.account.AccountType; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.common.logging.Logger; -import org.jbei.ice.lib.dao.DAOException; import org.jbei.ice.lib.dao.DAOFactory; import org.jbei.ice.lib.dao.hibernate.AccountDAO; import org.jbei.ice.lib.dao.hibernate.MessageDAO; @@ -18,6 +12,10 @@ import org.jbei.ice.lib.dto.message.MessageList; import org.jbei.ice.lib.group.Group; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + /** * @author Hector Plahar */ @@ -37,18 +35,13 @@ public MessageController() { * @param account account for user making the request. * @param id identifier for message to be marked as read * @return number of unread messages after marking message as read - * @throws ControllerException */ - public int markMessageAsRead(Account account, long id) throws ControllerException { - try { - Message message = dao.retrieveMessage(id); - message.setRead(true); - message.setDateRead(new Date(System.currentTimeMillis())); - dao.update(message); - return getNewMessageCount(account); - } catch (DAOException de) { - throw new ControllerException(de); - } + public int markMessageAsRead(Account account, long id) { + Message message = dao.retrieveMessage(id); + message.setRead(true); + message.setDateRead(new Date()); + dao.update(message); + return getNewMessageCount(account); } /** @@ -58,11 +51,10 @@ public int markMessageAsRead(Account account, long id) throws ControllerExceptio * @param sender account for user sending the message * @param info details of message including recipient(s) * @return false if the message fails to be sent to all the intended recipients - * @throws ControllerException */ - public boolean sendMessage(Account sender, MessageInfo info) throws ControllerException { + public boolean sendMessage(Account sender, MessageInfo info) { if (info == null || info.getAccounts().isEmpty() && info.getUserGroups().isEmpty()) - throw new ControllerException("Cannot send message"); + return false; boolean success = true; Message message = new Message(); @@ -98,11 +90,7 @@ public boolean sendMessage(Account sender, MessageInfo info) throws ControllerEx if (message.getDestinationAccounts().isEmpty() && message.getDestinationGroups().isEmpty()) return false; - try { - dao.create(message); - } catch (DAOException e) { - throw new ControllerException(e); - } + dao.create(message); return success; } @@ -135,11 +123,7 @@ public MessageList retrieveMessages(String requester, String owner, int start, i return messageList; } - public int getNewMessageCount(Account account) throws ControllerException { - try { - return dao.retrieveNewMessageCount(account); - } catch (DAOException de) { - throw new ControllerException(de); - } + public int getNewMessageCount(Account account) { + return dao.retrieveNewMessageCount(account); } } diff --git a/src/main/java/org/jbei/ice/services/rest/RestResource.java b/src/main/java/org/jbei/ice/services/rest/RestResource.java index fb9471046..21dd41b1b 100644 --- a/src/main/java/org/jbei/ice/services/rest/RestResource.java +++ b/src/main/java/org/jbei/ice/services/rest/RestResource.java @@ -1,17 +1,6 @@ package org.jbei.ice.services.rest; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.nio.file.Paths; -import java.security.Key; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; - +import org.apache.commons.lang3.StringUtils; import org.jbei.auth.KeyTable; import org.jbei.auth.hmac.HmacAuthorizor; import org.jbei.auth.hmac.HmacSignature; @@ -22,6 +11,17 @@ import org.jbei.ice.lib.dto.ConfigurationKey; import org.jbei.ice.lib.utils.Utils; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.nio.file.Paths; +import java.security.Key; + /** * Parent class for all rest resource objects * @@ -53,7 +53,7 @@ public Key getKey(final String keyId) { // collect all lines in the file to a buffer final StringBuilder encoded = new StringBuilder(); try (final FileReader reader = new FileReader(keyFile); - final BufferedReader buffered = new BufferedReader(reader);) { + final BufferedReader buffered = new BufferedReader(reader);) { String line; while ((line = buffered.readLine()) != null) { encoded.append(line); @@ -80,14 +80,11 @@ public Key getKey(final String keyId) { @Context private HttpServletRequest request; - private String userId = null; - /** * Extract the User ID from header values in the resource request. * * @return a string User ID - * @throws WebApplicationException - * for unauthorized access + * @throws WebApplicationException for unauthorized access */ protected String getUserId() { return getUserId(sessionId); @@ -96,62 +93,38 @@ protected String getUserId() { /** * Extract the User ID from a query parameter value or header values in the resource request. * - * @param sessionId - * a session ID sent via query parameters + * @param sessionId a session ID sent via query parameters * @return a string User ID - * @throws WebApplicationException - * for unauthorized access + * @throws WebApplicationException for unauthorized access */ protected String getUserId(final String sessionId) { - if (userId != null) { - // we've already looked up the userId + String userId = SessionHandler.getUserIdBySession(sessionId); + if (!StringUtils.isEmpty(userId)) return userId; - } else if ((userId = SessionHandler.getUserIdBySession(sessionId)) != null) { - // try to get user from a session ID, continue to Authorization if fails - } else { - final Object hmac = request.getAttribute(AuthenticationInterceptor.HMAC_SIGNATURE); - final Object valid = request.getAttribute(AuthenticationInterceptor.EXPECTED_SIGNATURE); - if (hmac != null && hmac instanceof HmacSignature) { - final HmacSignature generated = (HmacSignature) hmac; - if (generated.generateSignature().equals(valid)) { - // TODO validation of meaningful userId - // e.g. "admin" account on EDD won't mean anything to ICE - userId = generated.getUserId(); - } + + final Object hmac = request.getAttribute(AuthenticationInterceptor.HMAC_SIGNATURE); + final Object valid = request.getAttribute(AuthenticationInterceptor.EXPECTED_SIGNATURE); + if (hmac != null && hmac instanceof HmacSignature) { + final HmacSignature generated = (HmacSignature) hmac; + if (generated.generateSignature().equals(valid)) { + // TODO validation of meaningful userId + // e.g. "admin" account on EDD won't mean anything to ICE + userId = generated.getUserId(); } } - if (userId == null) { - throw new WebApplicationException(Response.Status.UNAUTHORIZED); - } - return userId; - } - /** - * @param sessionHeader - * not used - * @return the UserId of the user matching the session value - * @throws WebApplicationException - * if there is no valid UserId - * @deprecated use {@link #getUserId()} instead - */ - @Deprecated - protected String getUserIdFromSessionHeader(final String sessionHeader) { - final String userId = SessionHandler.getUserIdBySession(sessionId); - if (userId == null) { + if (userId == null) throw new WebApplicationException(Response.Status.UNAUTHORIZED); - } return userId; } /** * Create a {@link Response} object from an entity object. * - * @param status - * HTTP status code - * @param obj - * entity in response + * @param status HTTP status code + * @param obj entity in response * @return a Response object for the resource request, uses 500 error response if entity is - * {@code null} + * {@code null} */ protected Response respond(final Response.Status status, final Object obj) { if (obj == null) { @@ -164,8 +137,7 @@ protected Response respond(final Response.Status status, final Object obj) { /** * Create a {@link Response} object from an entity object. * - * @param object - * entity in response + * @param object entity in response * @return a 404 NOT FOUND if object is {@code null}, else a 200 OK response with the entity */ protected Response respond(final Object object) { @@ -179,8 +151,7 @@ protected Response respond(final Object object) { /** * Create an empty {@link Response} object. * - * @param status - * HTTP status code to use on the Response + * @param status HTTP status code to use on the Response * @return a Response object for the resource request */ protected Response respond(final Response.Status status) { @@ -190,8 +161,7 @@ protected Response respond(final Response.Status status) { /** * Create an empty {@link Response} object. * - * @param success - * success/failure flag + * @param success success/failure flag * @return a 200 OK response if success is {@code true}, otherwise a 500 error response */ protected Response respond(final boolean success) { @@ -204,10 +174,8 @@ protected Response respond(final boolean success) { /** * Used to log user actions * - * @param userId - * unique user identifier - * @param message - * log message + * @param userId unique user identifier + * @param message log message */ protected void log(final String userId, final String message) { final String who = (userId == null) ? "Unknown" : userId; diff --git a/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java b/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java index a57d5cd9c..14a2ba6f1 100644 --- a/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java +++ b/src/main/java/org/jbei/ice/services/rest/multipart/IceApplication.java @@ -1,15 +1,13 @@ package org.jbei.ice.services.rest.multipart; -import java.util.HashSet; -import java.util.Set; - -import javax.ws.rs.core.Application; - import org.glassfish.jersey.media.multipart.MultiPartFeature; - import org.jbei.ice.services.rest.AuthenticationInterceptor; import org.jbei.ice.services.rest.FileResource; +import javax.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Set; + /** * @author Hector Plahar */ @@ -17,7 +15,7 @@ public class IceApplication extends Application { @Override public Set> getClasses() { - final Set> classes = new HashSet>(); + final Set> classes = new HashSet<>(); // register resources and features classes.add(MultiPartFeature.class); classes.add(FileResource.class); From fad914870d243d94735f8ccf5cb0a5b586d24e8b Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 30 Jun 2015 10:43:48 -0700 Subject: [PATCH 41/67] removing unused method --- .../org/jbei/ice/lib/parsers/ABIParser.java | 9 +------- .../jbei/ice/lib/parsers/AbstractParser.java | 7 +++---- .../org/jbei/ice/lib/parsers/IDNAParser.java | 13 +++--------- .../org/jbei/ice/lib/parsers/PlainParser.java | 12 +---------- .../ice/lib/parsers/fasta/FastaParser.java | 21 +++++++------------ .../lib/parsers/genbank/IceGenbankParser.java | 8 ------- .../jbei/ice/lib/parsers/sbol/SBOLParser.java | 13 +++--------- 7 files changed, 18 insertions(+), 65 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/parsers/ABIParser.java b/src/main/java/org/jbei/ice/lib/parsers/ABIParser.java index a30bb8a6e..be5e94f22 100755 --- a/src/main/java/org/jbei/ice/lib/parsers/ABIParser.java +++ b/src/main/java/org/jbei/ice/lib/parsers/ABIParser.java @@ -1,10 +1,9 @@ package org.jbei.ice.lib.parsers; +import org.biojava.bio.symbol.SymbolList; import org.jbei.ice.lib.parsers.abi.ABITrace; import org.jbei.ice.lib.vo.DNASequence; -import org.biojava.bio.symbol.SymbolList; - /** * Parse ABI sequence trace file by wrappying BioJava. * @@ -19,12 +18,6 @@ public String getName() { return ABI_PARSER; } - @Override - public Boolean hasErrors() { - // This parser cannot succeed with errors, so always return false, or fail. - return false; - } - @Override public DNASequence parse(byte[] bytes) throws InvalidFormatParserException { DNASequence DNASequence = null; diff --git a/src/main/java/org/jbei/ice/lib/parsers/AbstractParser.java b/src/main/java/org/jbei/ice/lib/parsers/AbstractParser.java index 0b2a93259..f36f3a19a 100755 --- a/src/main/java/org/jbei/ice/lib/parsers/AbstractParser.java +++ b/src/main/java/org/jbei/ice/lib/parsers/AbstractParser.java @@ -1,13 +1,12 @@ package org.jbei.ice.lib.parsers; +import org.apache.commons.io.IOUtils; +import org.jbei.ice.lib.vo.DNASequence; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import org.jbei.ice.lib.vo.DNASequence; - -import org.apache.commons.io.IOUtils; - /** * This class provides skeletal implementation of {@link IDNAParser} interface. * diff --git a/src/main/java/org/jbei/ice/lib/parsers/IDNAParser.java b/src/main/java/org/jbei/ice/lib/parsers/IDNAParser.java index e1975950c..5860814cd 100755 --- a/src/main/java/org/jbei/ice/lib/parsers/IDNAParser.java +++ b/src/main/java/org/jbei/ice/lib/parsers/IDNAParser.java @@ -1,11 +1,11 @@ package org.jbei.ice.lib.parsers; +import org.jbei.ice.lib.vo.DNASequence; + import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import org.jbei.ice.lib.vo.DNASequence; - /** * An object that parser sequences and generates an annotated {@link DNASequence} object. * @@ -19,13 +19,6 @@ public interface IDNAParser { */ String getName(); - /** - * Return true if parsing was completed, but there maybe errors in the parsing. - * - * @return True if parsing has errors. - */ - Boolean hasErrors(); - /** * Parse the given bytes to {@link DNASequence} annotated sequence. * @@ -44,7 +37,7 @@ public interface IDNAParser { * @throws IOException * @throws InvalidFormatParserException */ - DNASequence parse(File file) throws FileNotFoundException, IOException, InvalidFormatParserException; + DNASequence parse(File file) throws IOException, InvalidFormatParserException; /** * Parse the given string to {@link DNASequence} annotated sequence. diff --git a/src/main/java/org/jbei/ice/lib/parsers/PlainParser.java b/src/main/java/org/jbei/ice/lib/parsers/PlainParser.java index f1da9a9e9..d9884f0dc 100755 --- a/src/main/java/org/jbei/ice/lib/parsers/PlainParser.java +++ b/src/main/java/org/jbei/ice/lib/parsers/PlainParser.java @@ -1,12 +1,10 @@ package org.jbei.ice.lib.parsers; -import org.jbei.ice.lib.vo.DNASequence; - import org.biojava.bio.BioException; import org.biojava.bio.seq.DNATools; -import org.biojava.bio.symbol.IllegalSymbolException; import org.biojava.bio.symbol.SimpleSymbolList; import org.biojava.bio.symbol.SymbolList; +import org.jbei.ice.lib.vo.DNASequence; /** * Parser to handle file with simply nucleotide sequences. Technically these files are not FASTA @@ -17,12 +15,6 @@ public class PlainParser extends AbstractParser { private static final String PLAIN_PARSER = "Plain"; - @Override - public Boolean hasErrors() { - // This parser cannot succeed with errors, so always return false, or fail. - return false; - } - @Override public DNASequence parse(String textSequence) throws InvalidFormatParserException { textSequence = cleanSequence(textSequence); @@ -31,8 +23,6 @@ public DNASequence parse(String textSequence) throws InvalidFormatParserExceptio try { sl = new SimpleSymbolList(DNATools.getDNA().getTokenization("token"), textSequence .replaceAll("\\s+", "").replaceAll("[\\.|~]", "-").replaceAll("[0-9]", "")); - } catch (IllegalSymbolException e) { - throw new InvalidFormatParserException("Couldn't parse Plain sequence!", e); } catch (BioException e) { throw new InvalidFormatParserException("Couldn't parse Plain sequence!", e); } diff --git a/src/main/java/org/jbei/ice/lib/parsers/fasta/FastaParser.java b/src/main/java/org/jbei/ice/lib/parsers/fasta/FastaParser.java index 266ff1f59..0f9bb33f8 100755 --- a/src/main/java/org/jbei/ice/lib/parsers/fasta/FastaParser.java +++ b/src/main/java/org/jbei/ice/lib/parsers/fasta/FastaParser.java @@ -1,19 +1,18 @@ package org.jbei.ice.lib.parsers.fasta; -import java.io.BufferedReader; -import java.io.StringReader; -import java.util.LinkedList; - +import org.biojava.bio.BioException; +import org.biojavax.bio.seq.RichSequence; +import org.biojavax.bio.seq.RichSequence.IOTools; +import org.biojavax.bio.seq.RichSequenceIterator; import org.jbei.ice.lib.parsers.AbstractParser; import org.jbei.ice.lib.parsers.InvalidFormatParserException; import org.jbei.ice.lib.vo.DNAFeature; import org.jbei.ice.lib.vo.DNASequence; import org.jbei.ice.lib.vo.FeaturedDNASequence; -import org.biojava.bio.BioException; -import org.biojavax.bio.seq.RichSequence; -import org.biojavax.bio.seq.RichSequence.IOTools; -import org.biojavax.bio.seq.RichSequenceIterator; +import java.io.BufferedReader; +import java.io.StringReader; +import java.util.LinkedList; /** * Parse FASTA files. @@ -28,12 +27,6 @@ public String getName() { return FASTA_PARSER; } - @Override - public Boolean hasErrors() { - //This parser cannot succeed with errors, so always return false, or fail. - return false; - } - @Override public FeaturedDNASequence parse(String textSequence) throws InvalidFormatParserException { textSequence = cleanSequence(textSequence); diff --git a/src/main/java/org/jbei/ice/lib/parsers/genbank/IceGenbankParser.java b/src/main/java/org/jbei/ice/lib/parsers/genbank/IceGenbankParser.java index 0cef66d1e..55066f752 100755 --- a/src/main/java/org/jbei/ice/lib/parsers/genbank/IceGenbankParser.java +++ b/src/main/java/org/jbei/ice/lib/parsers/genbank/IceGenbankParser.java @@ -58,7 +58,6 @@ public class IceGenbankParser extends AbstractParser { private static final Pattern startStopPattern = Pattern.compile("[<>]*(\\d+)\\.\\.[<>]*(\\d+)"); private static final Pattern startOnlyPattern = Pattern.compile("\\d+"); - private Boolean hasErrors = false; private List errors = new ArrayList<>(); @Override @@ -66,11 +65,6 @@ public String getName() { return ICE_GENBANK_PARSER; } - @Override - public Boolean hasErrors() { - return hasErrors; - } - public List getErrors() { return errors; } @@ -351,7 +345,6 @@ private FeaturesTag parseFeaturesTag(final Tag tag) throws InvalidFormatParserEx } } catch (final NumberFormatException e) { getErrors().add("Could not parse feature " + line); - hasErrors = true; continue; } @@ -456,7 +449,6 @@ private DNAFeature parseQualifiers(final String block, DNAFeature dnaFeature) { chunk = line.split("="); if (chunk.length < 2) { getErrors().add("Skipping bad genbank qualifier " + line); - hasErrors = true; dnaFeatureNote = null; } else { final String putativeName = chunk[0].trim().substring(1); diff --git a/src/main/java/org/jbei/ice/lib/parsers/sbol/SBOLParser.java b/src/main/java/org/jbei/ice/lib/parsers/sbol/SBOLParser.java index 836132c3c..833178411 100755 --- a/src/main/java/org/jbei/ice/lib/parsers/sbol/SBOLParser.java +++ b/src/main/java/org/jbei/ice/lib/parsers/sbol/SBOLParser.java @@ -1,17 +1,16 @@ package org.jbei.ice.lib.parsers.sbol; -import java.io.ByteArrayInputStream; -import java.io.IOException; - import org.jbei.ice.lib.parsers.AbstractParser; import org.jbei.ice.lib.parsers.InvalidFormatParserException; import org.jbei.ice.lib.vo.DNASequence; - import org.sbolstandard.core.SBOLDocument; import org.sbolstandard.core.SBOLFactory; import org.sbolstandard.core.SBOLRootObject; import org.sbolstandard.core.SBOLValidationException; +import java.io.ByteArrayInputStream; +import java.io.IOException; + /** * Parse SBOL (v 1.1) files that are imported by the user * @@ -26,12 +25,6 @@ public String getName() { return SBOL_PARSER; } - @Override - public Boolean hasErrors() { - // This parser cannot succeed with errors, so always return false, or fail. - return false; - } - @Override public DNASequence parse(String textSequence) throws InvalidFormatParserException { try { From 5a7102e440a566925ea61fc3a6cbe8212ce8b2f3 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 30 Jun 2015 10:44:09 -0700 Subject: [PATCH 42/67] upgrading package --- pom.xml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index d91793688..fb114a454 100755 --- a/pom.xml +++ b/pom.xml @@ -8,11 +8,6 @@ ice Inventory of Composable Elements (ICE) for Synthetic Biology - - biojava-maven-repo - BioJava repository - http://www.biojava.org/download/maven/ - Sonatype OSS Snapshot Repository https://oss.sonatype.org/content/repositories/snapshots/ @@ -105,7 +100,7 @@ org.biojava core - 1.8.5 + 1.9.2 org.sbolstandard From b42b7eddaf4058b517881a5882ac1e9bc9a4c385 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Mon, 17 Aug 2015 12:44:12 -0700 Subject: [PATCH 43/67] bug fix: query type and boolean clause are not the same --- .../org/jbei/ice/lib/entry/model/Entry.java | 5 +++-- .../jbei/ice/lib/search/HibernateSearch.java | 12 ++++++------ .../java/org/jbei/ice/lib/search/QueryType.java | 9 +++++++++ .../jbei/ice/lib/search/SearchController.java | 15 +++++++-------- .../ice/lib/search/SearchControllerTest.java | 17 ++++++++--------- 5 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 src/main/java/org/jbei/ice/lib/search/QueryType.java diff --git a/src/main/java/org/jbei/ice/lib/entry/model/Entry.java b/src/main/java/org/jbei/ice/lib/entry/model/Entry.java index 440e5522e..96eb5764f 100755 --- a/src/main/java/org/jbei/ice/lib/entry/model/Entry.java +++ b/src/main/java/org/jbei/ice/lib/entry/model/Entry.java @@ -1,7 +1,7 @@ package org.jbei.ice.lib.entry.model; import org.apache.lucene.analysis.core.LowerCaseFilterFactory; -import org.apache.lucene.analysis.standard.StandardTokenizerFactory; +import org.apache.lucene.analysis.ngram.EdgeNGramTokenizerFactory; import org.hibernate.annotations.Type; import org.hibernate.search.annotations.*; import org.hibernate.search.annotations.Index; @@ -80,7 +80,7 @@ @FullTextFilterDef(name = "boolean", impl = EntryHasFilterFactory.class, cache = FilterCacheModeType.INSTANCE_ONLY) }) @AnalyzerDef(name = "customanalyzer", - tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class), + tokenizer = @TokenizerDef(factory = EdgeNGramTokenizerFactory.class), filters = { @TokenFilterDef(factory = LowerCaseFilterFactory.class), }) @@ -128,6 +128,7 @@ public class Entry implements IDataModel { @Column(name = "name", length = 127) @Field(store = Store.YES, boost = @Boost(4f)) + @Analyzer(definition = "customanalyzer") private String name; @Column(name = "part_number", length = 127) diff --git a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java index 27a644412..cb693a707 100755 --- a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java +++ b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java @@ -59,16 +59,16 @@ public static HibernateSearch getInstance() { } protected BooleanQuery generateQueriesForType(FullTextSession fullTextSession, HashSet fields, - BooleanQuery booleanQuery, String term, BooleanClause.Occur occur, BioSafetyOption option, - HashMap userBoost) { + BooleanQuery booleanQuery, String term, QueryType type, + BioSafetyOption option, HashMap userBoost) { QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Entry.class).get(); if (!StringUtils.isEmpty(term)) { // generate term queries for each search term for (String field : fields) { Query query; - if (occur == BooleanClause.Occur.MUST) - query = qb.phrase().withSlop(3).onField(field).sentence(term).createQuery(); + if (type == QueryType.PHRASE) + query = qb.phrase().onField(field).sentence(term).createQuery(); else if (term.contains("*")) { if (!field.equals("name")) continue; @@ -278,7 +278,7 @@ public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws return results; } - public SearchResults executeSearch(String userId, HashMap terms, + public SearchResults executeSearch(String userId, HashMap terms, SearchQuery searchQuery, HashMap userBoost, HashMap blastResults) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); @@ -292,7 +292,7 @@ public SearchResults executeSearch(String userId, HashMap[] classes = SearchFieldFactory.classesForTypes(searchQuery.getEntryTypes()); // generate queries for terms filtering stop words - for (Map.Entry entry : terms.entrySet()) { + for (Map.Entry entry : terms.entrySet()) { String term = cleanQuery(entry.getKey()); if (term.trim().isEmpty() || StandardAnalyzer.STOP_WORDS_SET.contains(term)) continue; diff --git a/src/main/java/org/jbei/ice/lib/search/QueryType.java b/src/main/java/org/jbei/ice/lib/search/QueryType.java new file mode 100644 index 000000000..5d08b438c --- /dev/null +++ b/src/main/java/org/jbei/ice/lib/search/QueryType.java @@ -0,0 +1,9 @@ +package org.jbei.ice.lib.search; + +/** + * @author Hector Plahar + */ +public enum QueryType { + PHRASE, + TERM +} diff --git a/src/main/java/org/jbei/ice/lib/search/SearchController.java b/src/main/java/org/jbei/ice/lib/search/SearchController.java index b2179976b..12f32d2a7 100755 --- a/src/main/java/org/jbei/ice/lib/search/SearchController.java +++ b/src/main/java/org/jbei/ice/lib/search/SearchController.java @@ -1,7 +1,6 @@ package org.jbei.ice.lib.search; import org.apache.commons.lang.StringUtils; -import org.apache.lucene.search.BooleanClause; import org.jbei.ice.lib.account.AccountController; import org.jbei.ice.lib.common.logging.Logger; import org.jbei.ice.lib.dao.DAOFactory; @@ -143,7 +142,7 @@ public SearchResults runLocalSearch(String userId, SearchQuery query) { // } if (!StringUtils.isEmpty(queryString)) { - HashMap terms = parseQueryString(queryString); + HashMap terms = parseQueryString(queryString); return hibernateSearch.executeSearch(userId, terms, query, mapping, blastResults); } else { return hibernateSearch.executeSearchNoTerms(userId, blastResults, query); @@ -189,8 +188,8 @@ else if (type == IndexType.BLAST) { * @return a mapping of the phrases and terms to clauses that indicate how the matches should appear * in the document. Phrases must appear in the result document */ - HashMap parseQueryString(String queryString) { - HashMap terms = new HashMap<>(); + HashMap parseQueryString(String queryString) { + HashMap terms = new HashMap<>(); if (queryString == null || queryString.trim().length() == 0) return terms; @@ -201,7 +200,7 @@ HashMap parseQueryString(String queryString) { char c = queryString.charAt(i); if (c == '\"' || c == '\'') { if (startedPhrase) { - terms.put(builder.toString(), BooleanClause.Occur.MUST); + terms.put(builder.toString(), QueryType.PHRASE); builder = new StringBuilder(); startedPhrase = false; } else { @@ -216,7 +215,7 @@ HashMap parseQueryString(String queryString) { continue; if (!startedPhrase) { - terms.put(builder.toString(), BooleanClause.Occur.SHOULD); + terms.put(builder.toString(), QueryType.TERM); builder = new StringBuilder(); continue; } @@ -226,9 +225,9 @@ HashMap parseQueryString(String queryString) { } if (builder.length() > 0) { if (startedPhrase) - terms.put(builder.toString(), BooleanClause.Occur.MUST); + terms.put(builder.toString(), QueryType.PHRASE); else - terms.put(builder.toString(), BooleanClause.Occur.SHOULD); + terms.put(builder.toString(), QueryType.TERM); } return terms; diff --git a/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java b/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java index 5924d8989..65b9ae4a1 100644 --- a/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java +++ b/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java @@ -1,6 +1,5 @@ package org.jbei.ice.lib.search; -import org.apache.lucene.search.BooleanClause; import org.jbei.ice.lib.AccountCreator; import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.dao.hibernate.HibernateUtil; @@ -42,15 +41,15 @@ public void tearDown() throws Exception { @Test public void testParseQueryString() throws Exception { String query = "\"the quick\" brown fox jumped \"over\" \"the\" moon"; - HashMap result = controller.parseQueryString(query); + HashMap result = controller.parseQueryString(query); Assert.assertNotNull(result); - Assert.assertEquals(result.get("the quick"), BooleanClause.Occur.MUST); - Assert.assertEquals(result.get("brown"), BooleanClause.Occur.SHOULD); - Assert.assertEquals(result.get("fox"), BooleanClause.Occur.SHOULD); - Assert.assertEquals(result.get("jumped"), BooleanClause.Occur.SHOULD); - Assert.assertEquals(result.get("over"), BooleanClause.Occur.MUST); - Assert.assertEquals(result.get("the"), BooleanClause.Occur.MUST); - Assert.assertEquals(result.get("moon"), BooleanClause.Occur.SHOULD); + Assert.assertEquals(result.get("the quick"), QueryType.PHRASE); + Assert.assertEquals(result.get("brown"), QueryType.TERM); + Assert.assertEquals(result.get("fox"), QueryType.TERM); + Assert.assertEquals(result.get("jumped"), QueryType.TERM); + Assert.assertEquals(result.get("over"), QueryType.PHRASE); + Assert.assertEquals(result.get("the"), QueryType.PHRASE); + Assert.assertEquals(result.get("moon"), QueryType.TERM); } @Test From ca4609cdb0e61845ad0295741370b50fdc6ed5ec Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 18 Aug 2015 15:47:31 -0700 Subject: [PATCH 44/67] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e358d2576..9bcf99945 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,3 @@ language: java jdk: - - oraclejdk7 + - oraclejdk8 From 212fbcc7b15a77fa68341ae64ec86d5c149d6c89 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Fri, 21 Aug 2015 14:41:37 -0700 Subject: [PATCH 45/67] SYNBIO-969: adding ability to add custom fields/parameters to existing entries --- .../jbei/ice/lib/dto/entry/CustomField.java | 2 +- .../lib/search/filter/SearchFieldFactory.java | 1 + .../services/rest/CustomFieldResource.java | 3 + .../ice/services/rest/SampleResource.java | 6 +- .../webapp/scripts/entry/entryController.js | 26 +- src/main/webapp/scripts/entry/entryService.js | 17 +- .../scripts/entry/general-information.html | 523 ++++++++++-------- 7 files changed, 329 insertions(+), 249 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java b/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java index 87a2d4c7a..823f3f08a 100755 --- a/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java +++ b/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java @@ -3,7 +3,7 @@ import org.jbei.ice.lib.dao.IDataTransferModel; /** - * User created fields for entry + * User created key/value pair fields for an entry. * * @author Hector Plahar */ diff --git a/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java b/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java index 1b77001b0..3f3e06bbc 100644 --- a/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java +++ b/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java @@ -38,6 +38,7 @@ public class SearchFieldFactory { commonFields.add("links.link"); commonFields.add("links.url"); commonFields.add("selectionMarkers.name"); + commonFields.add("parameters.value"); commonFields.add("fundingSource"); commonFields.add("principalInvestigator"); diff --git a/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java b/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java index f841a2726..7932d1a7a 100644 --- a/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java +++ b/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java @@ -46,6 +46,9 @@ public Response create( if (partId <= 0) partId = customField.getPartId(); + if (partId <= 0) + throw new WebApplicationException("Invalid part id", Response.Status.BAD_REQUEST); + if (fields.createField(userId, partId, customField) > 0) return super.respond(Response.Status.CREATED); return super.respond(false); diff --git a/src/main/java/org/jbei/ice/services/rest/SampleResource.java b/src/main/java/org/jbei/ice/services/rest/SampleResource.java index 74f523365..41a251e12 100644 --- a/src/main/java/org/jbei/ice/services/rest/SampleResource.java +++ b/src/main/java/org/jbei/ice/services/rest/SampleResource.java @@ -30,9 +30,11 @@ public class SampleResource extends RestResource { @GET @Produces(MediaType.APPLICATION_JSON) @Path("{token}") - public Response getSampleByToken(@PathParam("token") String token) { + public Response getSampleByToken(@PathParam("token") String token, + @HeaderParam(value = "X-ICE-Authentication-SessionId") String userAgentHeader) { try { - ArrayList result = sampleService.getSamplesByBarcode(null, token); + String userId = getUserIdFromSessionHeader(userAgentHeader); + ArrayList result = sampleService.getSamplesByBarcode(userId, token); return super.respond(result); } catch (Exception e) { Logger.error(e); diff --git a/src/main/webapp/scripts/entry/entryController.js b/src/main/webapp/scripts/entry/entryController.js index 7d6a17bcd..d3c701f9f 100644 --- a/src/main/webapp/scripts/entry/entryController.js +++ b/src/main/webapp/scripts/entry/entryController.js @@ -934,7 +934,8 @@ angular.module('ice.entry.controller', []) }) .controller('EntryController', function ($scope, $stateParams, $cookieStore, $location, $modal, $rootScope, - FileUploader, Entry, Folders, EntryService, EntryContextUtil, Selection) { + FileUploader, Entry, Folders, EntryService, EntryContextUtil, Selection, + CustomField) { $scope.partIdEditMode = false; $scope.showSBOL = true; $scope.context = EntryContextUtil.getContext(); @@ -1096,6 +1097,8 @@ angular.module('ice.entry.controller', []) Selection.selectEntry(result); $scope.entry = EntryService.convertToUIForm(result); + if ($scope.entry.canEdit) + $scope.newParameter = {edit: false}; $scope.entryFields = EntryService.getFieldsForType(result.type.toLowerCase()); entry.statistics({partId: $stateParams.id}, function (stats) { @@ -1297,5 +1300,26 @@ angular.module('ice.entry.controller', []) uploader.onErrorItem = function (item, response, status, headers) { $scope.serverError = true; }; + + // customer parameter add for entry view + $scope.addNewCustomField = function () { + $scope.newParameter.nameInvalid = $scope.newParameter.name == undefined || $scope.newParameter.name == ''; + $scope.newParameter.valueInvalid = $scope.newParameter.value == undefined || $scope.newParameter.value == ''; + if ($scope.newParameter.nameInvalid || $scope.newParameter.valueInvalid) + return; + + $scope.newParameter.partId = $scope.entry.id; + CustomField().createNewCustomField( + $scope.newParameter, + function (result) { + if (!result) + return; + + $scope.entry.parameters.push(result); + $scope.newParameter.edit = false; + }, function (error) { + console.error(error); + }) + } }); diff --git a/src/main/webapp/scripts/entry/entryService.js b/src/main/webapp/scripts/entry/entryService.js index fdb20ce0c..7e62fc6f5 100644 --- a/src/main/webapp/scripts/entry/entryService.js +++ b/src/main/webapp/scripts/entry/entryService.js @@ -449,4 +449,19 @@ angular.module('ice.entry.service', []) return entry; } } - }); + }) + .factory('CustomField', function ($resource, $cookieStore) { + return function () { + + var sessionId = $cookieStore.get("sessionId"); + + return $resource('rest/custom-fields', {}, { + createNewCustomField: { + method: 'POST', + responseType: "json", + headers: {'X-ICE-Authentication-SessionId': sessionId} + } + }); + } + }) +; diff --git a/src/main/webapp/scripts/entry/general-information.html b/src/main/webapp/scripts/entry/general-information.html index 35087ce28..53b1c63a3 100644 --- a/src/main/webapp/scripts/entry/general-information.html +++ b/src/main/webapp/scripts/entry/general-information.html @@ -1,161 +1,163 @@

- -
- -
{{entry.partId}}
-
- - -
- - - -
-
- -
- {{entry[field.schema].toString()}} + +
+ +
{{entry.partId}}
+
+ + +
+ + + +
+ + +
+ {{entry[field.schema].toString()}} -
+
- -
- {{entry[field.schema]}} - ({{entry[field.schema+'Email']}}) - {{entry[field.schema]}} ({{entry[field.schema+'Email']}}) + +
+ {{entry[field.schema]}} + ({{entry[field.schema+'Email']}}) + {{entry[field.schema]}} ({{entry[field.schema+'Email']}}) -
+
- -
{{entry[field.schema] | date:'fullDate' }} + +
{{entry[field.schema] | date:'fullDate' }} -
+
- - -
- + + +
+ -   +   Update Cancel -
+
- -
- + +
+ - + Save Cancel -
+
- -
- + +
+ Save Cancel -
+
- -
- + +
+ Save Cancel -
+
- -
date -
- + +
date +
+ -
+
Save Cancel -
+
- -
- + +
+ Save Cancel -
+
- -
- - + +
+ + Save Cancel -
+
- -
+ +
-
+
- -
+ +
-
+
- -
+ +
-
+
Save Cancel +
+ + +
- - +
-
-
+
+ -
- -
- {{parameter.value}} + +
+ +
+
+ +
+ +
+ + + Save + Cancel + +
+
+ +
+ +
-
- -
-
-
CONTAINS
- -
-
-
-
- -
- - - {{entry.linkedParts[$index+0].type}} {{entry.linkedParts[$index+0].name}} -
-
+ +
+
+
CONTAINS
+ +
+
+
+
+ +
+ + + {{entry.linkedParts[$index+0].type}} {{entry.linkedParts[$index+0].name}} +
+ +
Sequence with {{entry.linkedParts[$index+0].basePairCount | number}} base pairs & {{entry.linkedParts[$index+0].featureCount}} features @@ -269,116 +299,119 @@ No sequence data +
+

+ {{entry.linkedParts[$index+0].shortDescription}}

-

- {{entry.linkedParts[$index+0].shortDescription}}

-
-
-
-
- {{entry.linkedParts[$index+1].partId}} +
+
+ +
+ + + {{entry.linkedParts[$index+1].type}} {{entry.linkedParts[$index+1].name}} +
+ +
+ Sequence with {{entry.linkedParts[$index+1].basePairCount | number}} base pairs & {{entry.linkedParts[$index+1].featureCount}} features +
+

+ {{entry.linkedParts[$index+1].shortDescription}}

-
- - - {{entry.linkedParts[$index+1].type}} {{entry.linkedParts[$index+1].name}} -
- -
- Sequence with {{entry.linkedParts[$index+1].basePairCount | number}} base pairs & {{entry.linkedParts[$index+1].featureCount}} features -
-

- {{entry.linkedParts[$index+1].shortDescription}}

-
- -
-
-
- SEQUENCE - - -
- Create in VectorEditor - -   |   - -   Upload File - -   |   - - Paste Sequence - -
- -
+
+
+
+ SEQUENCE + + +
+ Create in VectorEditor + +   |   + +   Upload File + +   |   + + Paste Sequence + +
+ + +
Delete   |   - - Open in VectorEditor - + + Open in VectorEditor + -   |   +   |   - + - - - - -   |   - - - Hide - Show Pigeon Image - + + + + +   |   + + + Hide + Show Pigeon Image + +
-
- -
- No sequence data provided + +
+ No sequence data provided - +
Supported file formats are @@ -389,7 +422,8 @@ Error parsing file
-
+
+
@@ -400,32 +434,33 @@ Processing file {{processingFile}} - + -
+
- -
-
- + +
+
+ +
-
-
- +
+ +
-
-
-
-
- NOTES +
+
+
+ NOTES +
+ {{entry.longDescription}}
- {{entry.longDescription}}
-
\ No newline at end of file From 50ac3a4554390b04c623da33aa9f03ef53daea55 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Fri, 21 Aug 2015 20:40:09 -0700 Subject: [PATCH 46/67] adding api to retrieve entries by custom fields --- .../ice/lib/dao/hibernate/ParameterDAO.java | 21 ++++++++++ .../jbei/ice/lib/dto/entry/CustomField.java | 11 ++++++ .../jbei/ice/lib/dto/entry/CustomFields.java | 14 +++++++ .../org/jbei/ice/lib/entry/model/Entry.java | 1 - .../services/rest/CustomFieldResource.java | 29 +++++++++++++- .../ice/lib/dto/entry/CustomFieldsTest.java | 38 ++++++++++++++++++- 6 files changed, 109 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/dao/hibernate/ParameterDAO.java b/src/main/java/org/jbei/ice/lib/dao/hibernate/ParameterDAO.java index 4c121ec60..2edcffd46 100644 --- a/src/main/java/org/jbei/ice/lib/dao/hibernate/ParameterDAO.java +++ b/src/main/java/org/jbei/ice/lib/dao/hibernate/ParameterDAO.java @@ -1,8 +1,17 @@ package org.jbei.ice.lib.dao.hibernate; +import org.hibernate.Criteria; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; +import org.jbei.ice.lib.dto.entry.CustomField; +import org.jbei.ice.lib.entry.model.Entry; import org.jbei.ice.lib.entry.model.Parameter; +import java.util.List; + /** + * Data accessor object for handling {@link Parameter}s + * * @author Hector Plahar */ public class ParameterDAO extends HibernateRepository { @@ -11,4 +20,16 @@ public class ParameterDAO extends HibernateRepository { public Parameter get(long id) { return super.get(Parameter.class, id); } + + // filter by key value pairs + public List filter(List fields) { + Criteria criteria = currentSession().createCriteria(Parameter.class); + for (CustomField field : fields) { + criteria.add( + Restrictions.and( + Restrictions.eq("key", field.getName()), Restrictions.eq("value", field.getValue()))); + } + criteria.setProjection(Projections.property("entry")); + return criteria.list(); + } } diff --git a/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java b/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java index 823f3f08a..faf34b119 100755 --- a/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java +++ b/src/main/java/org/jbei/ice/lib/dto/entry/CustomField.java @@ -17,6 +17,17 @@ public class CustomField implements IDataTransferModel { public CustomField() { } + public CustomField(String name, String value) { + this.name = name; + this.value = value; + } + + public CustomField(long partId, String name, String value) { + this.partId = partId; + this.name = name; + this.value = value; + } + public CustomField(long id, long partId, String name, String value) { this.id = id; this.name = name; diff --git a/src/main/java/org/jbei/ice/lib/dto/entry/CustomFields.java b/src/main/java/org/jbei/ice/lib/dto/entry/CustomFields.java index ee831ef9b..3e3eb0ca3 100644 --- a/src/main/java/org/jbei/ice/lib/dto/entry/CustomFields.java +++ b/src/main/java/org/jbei/ice/lib/dto/entry/CustomFields.java @@ -76,6 +76,20 @@ public List getFieldsForPart(String userId, long partId) { return result; } + public List getPartsByFields(String userId, List fields) { + // todo : performance + List entries = dao.filter(fields); + List parts = new ArrayList<>(); + for (Entry entry : entries) { + if (!authorization.canRead(userId, entry)) + continue; + + parts.add(entry.toDataTransferObject()); + } + + return parts; + } + /** * Deletes the custom field specified by the unique identifier in the parameter. * The user must have write privileges on field associated with entry diff --git a/src/main/java/org/jbei/ice/lib/entry/model/Entry.java b/src/main/java/org/jbei/ice/lib/entry/model/Entry.java index 96eb5764f..4dffde350 100755 --- a/src/main/java/org/jbei/ice/lib/entry/model/Entry.java +++ b/src/main/java/org/jbei/ice/lib/entry/model/Entry.java @@ -128,7 +128,6 @@ public class Entry implements IDataModel { @Column(name = "name", length = 127) @Field(store = Store.YES, boost = @Boost(4f)) - @Analyzer(definition = "customanalyzer") private String name; @Column(name = "part_number", length = 127) diff --git a/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java b/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java index 7932d1a7a..09e84fe62 100644 --- a/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java +++ b/src/main/java/org/jbei/ice/services/rest/CustomFieldResource.java @@ -4,8 +4,8 @@ import org.jbei.ice.lib.dto.entry.CustomFields; import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; +import javax.ws.rs.core.*; +import java.util.ArrayList; import java.util.List; /** @@ -18,6 +18,31 @@ public class CustomFieldResource extends RestResource { private CustomFields fields = new CustomFields(); + @GET + @Path("/parts") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getPartByCustomFields( + @Context UriInfo uriInfo, + @HeaderParam(value = "X-ICE-Authentication-SessionId") String sid) { + MultivaluedMap queryParams = uriInfo.getQueryParameters(); + if (queryParams.isEmpty()) + return super.respond(new ArrayList<>()); + + String userId = getUserIdFromSessionHeader(sid); + + List fieldList = new ArrayList<>(); + for (String key : queryParams.keySet()) { + List values = queryParams.get(key); + // currently disallowing multiple values + // todo : disjunction for same values + CustomField field = new CustomField(key, values.get(0)); + fieldList.add(field); + } + + return super.respond(fields.getPartsByFields(userId, fieldList)); + } + /** * Creates a new custom field and associated it with the specified entry. * There are two ways to specify the entry to associate the field with: diff --git a/src/test/java/org/jbei/ice/lib/dto/entry/CustomFieldsTest.java b/src/test/java/org/jbei/ice/lib/dto/entry/CustomFieldsTest.java index c471288ae..2979885b0 100644 --- a/src/test/java/org/jbei/ice/lib/dto/entry/CustomFieldsTest.java +++ b/src/test/java/org/jbei/ice/lib/dto/entry/CustomFieldsTest.java @@ -5,12 +5,14 @@ import org.jbei.ice.lib.account.model.Account; import org.jbei.ice.lib.dao.DAOFactory; import org.jbei.ice.lib.dao.hibernate.HibernateUtil; +import org.jbei.ice.lib.entry.model.Plasmid; import org.jbei.ice.lib.entry.model.Strain; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -109,7 +111,7 @@ public void testGetFieldsForPart() throws Exception { HashSet ids = new HashSet<>(); for (int i = 1; i <= 10; i += 1) { - CustomField field = new CustomField(0, strain.getId(), "name" + i, "value" + i); + CustomField field = new CustomField(strain.getId(), "name" + i, "value" + i); long id = fields.createField(userId, strain.getId(), field); ids.add(id); } @@ -130,7 +132,7 @@ public void testDeleteField() throws Exception { final String userId = account.getEmail(); Strain strain = TestEntryCreator.createTestStrain(account); Assert.assertNotNull(strain); - CustomField field = new CustomField(0, strain.getId(), "foo3", "bar3"); + CustomField field = new CustomField(strain.getId(), "foo3", "bar3"); long id = fields.createField(userId, strain.getId(), field); // verify custom field creation @@ -151,4 +153,36 @@ public void testDeleteField() throws Exception { Assert.assertNotNull(strain); Assert.assertTrue(strain.getParameters().isEmpty()); } + + @Test + public void testGetPartsByFields() throws Exception { + // create part + Account account = AccountCreator.createTestAccount("testGetPartsByFields", false); + final String userId = account.getEmail(); + Strain strain = TestEntryCreator.createTestStrain(account); + Assert.assertNotNull(strain); + + // create fields for strain + long strainId = strain.getId(); + fields.createField(userId, strainId, new CustomField(strainId, "type", "promoter")); + fields.createField(userId, strainId, new CustomField(strainId, "strength", "weak")); + + // search + List searchFields = new ArrayList<>(); + searchFields.add(new CustomField("strength", "weak")); + List results = fields.getPartsByFields(userId, searchFields); + Assert.assertEquals(1, results.size()); + Assert.assertEquals(strain.getId(), results.get(0).getId()); + + // create additional entry + Plasmid plasmid = TestEntryCreator.createTestPlasmid(account); + Assert.assertNotNull(plasmid); + long plasmidId = plasmid.getId(); + fields.createField(userId, plasmidId, new CustomField(plasmidId, "strength", "strong")); + searchFields.clear(); + searchFields.add(new CustomField("strength", "strong")); + results = fields.getPartsByFields(userId, searchFields); + Assert.assertEquals(1, results.size()); + Assert.assertEquals(plasmid.getId(), results.get(0).getId()); + } } \ No newline at end of file From 14c5601c1bf6488faeed80c42cf51ea47ab48829 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Mon, 24 Aug 2015 09:42:01 -0700 Subject: [PATCH 47/67] removing user search preferences --- .../jbei/ice/lib/search/HibernateSearch.java | 10 +++------- .../jbei/ice/lib/search/SearchController.java | 14 +------------- .../webapp/scripts/profile/preferences.html | 18 ------------------ .../ice/lib/search/SearchControllerTest.java | 3 ++- 4 files changed, 6 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java index cb693a707..a49254532 100755 --- a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java +++ b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java @@ -60,7 +60,7 @@ public static HibernateSearch getInstance() { protected BooleanQuery generateQueriesForType(FullTextSession fullTextSession, HashSet fields, BooleanQuery booleanQuery, String term, QueryType type, - BioSafetyOption option, HashMap userBoost) { + BioSafetyOption option) { QueryBuilder qb = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Entry.class).get(); if (!StringUtils.isEmpty(term)) { // generate term queries for each search term @@ -77,10 +77,6 @@ else if (term.contains("*")) { query = qb.keyword().fuzzy().withEditDistanceUpTo(1).onField(field).ignoreFieldBridge().matching( term).createQuery(); - Float boost = userBoost.get(field); - if (boost != null) - query.setBoost(boost); - booleanQuery.add(query, BooleanClause.Occur.SHOULD); } @@ -279,7 +275,7 @@ public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws } public SearchResults executeSearch(String userId, HashMap terms, - SearchQuery searchQuery, HashMap userBoost, + SearchQuery searchQuery, HashMap blastResults) { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); int resultCount; @@ -299,7 +295,7 @@ public SearchResults executeSearch(String userId, HashMap ter BioSafetyOption safetyOption = searchQuery.getBioSafetyOption(); booleanQuery = generateQueriesForType(fullTextSession, fields, booleanQuery, term, entry.getValue(), - safetyOption, userBoost); + safetyOption); } // check for blast search results filter diff --git a/src/main/java/org/jbei/ice/lib/search/SearchController.java b/src/main/java/org/jbei/ice/lib/search/SearchController.java index 12f32d2a7..b3818e09e 100755 --- a/src/main/java/org/jbei/ice/lib/search/SearchController.java +++ b/src/main/java/org/jbei/ice/lib/search/SearchController.java @@ -129,25 +129,13 @@ public SearchResults runLocalSearch(String userId, SearchQuery query) { // text query (may also include blast) // no filter type indicates a term or phrase query HibernateSearch hibernateSearch = HibernateSearch.getInstance(); - // List boostFields = Arrays.asList(SearchBoostField.values()); -// HashMap results = new PreferencesController().retrieveUserPreferenceList(account, boostFields); - HashMap mapping = new HashMap<>(); -// for (Map.Entry entry : results.entrySet()) { -// try { -// String field = SearchBoostField.valueOf(entry.getKey()).getField(); -// mapping.put(field, Float.valueOf(entry.getValue())); -// } catch (IllegalArgumentException nfe) { -// Logger.warn(nfe.getMessage()); -// } -// } if (!StringUtils.isEmpty(queryString)) { HashMap terms = parseQueryString(queryString); - return hibernateSearch.executeSearch(userId, terms, query, mapping, blastResults); + return hibernateSearch.executeSearch(userId, terms, query, blastResults); } else { return hibernateSearch.executeSearchNoTerms(userId, blastResults, query); } - } /** diff --git a/src/main/webapp/scripts/profile/preferences.html b/src/main/webapp/scripts/profile/preferences.html index 8deffe0b1..addae04f6 100644 --- a/src/main/webapp/scripts/profile/preferences.html +++ b/src/main/webapp/scripts/profile/preferences.html @@ -42,23 +42,5 @@
- - -
- Select a value to boost the relevance of the - result for that field. -
- -
- -
- -
-
-
\ No newline at end of file diff --git a/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java b/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java index 65b9ae4a1..96d95def0 100644 --- a/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java +++ b/src/test/java/org/jbei/ice/lib/search/SearchControllerTest.java @@ -61,9 +61,10 @@ public void testRunSearch() throws Exception { PlasmidData plasmidData = new PlasmidData(); plasmidData.setCircular(true); plasmidData.setPromoters("pTet"); + plasmidData.setOriginOfReplication("oRep"); + PartData partData = new PartData(EntryType.PLASMID); partData.setBioSafetyLevel(BioSafetyOption.LEVEL_ONE.ordinal()); - plasmidData.setOriginOfReplication("oRep"); partData.setStatus("Complete"); partData.setName("testPlasmid"); partData.setFundingSource("DOE"); From 9a889da3c0fddab1fb4888370a2d205d5e1aa5cf Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 25 Aug 2015 09:34:09 -0700 Subject: [PATCH 48/67] decreasing boost for name --- src/main/java/org/jbei/ice/lib/entry/model/Entry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jbei/ice/lib/entry/model/Entry.java b/src/main/java/org/jbei/ice/lib/entry/model/Entry.java index 4dffde350..a5665b11d 100755 --- a/src/main/java/org/jbei/ice/lib/entry/model/Entry.java +++ b/src/main/java/org/jbei/ice/lib/entry/model/Entry.java @@ -127,7 +127,7 @@ public class Entry implements IDataModel { private String alias; @Column(name = "name", length = 127) - @Field(store = Store.YES, boost = @Boost(4f)) + @Field(store = Store.YES, boost = @Boost(2f)) private String name; @Column(name = "part_number", length = 127) From 24c560b538e12ef5a232233e4362d54bf787ea68 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 25 Aug 2015 09:35:11 -0700 Subject: [PATCH 49/67] extending kleene star search to other common fields --- .../jbei/ice/lib/search/HibernateSearch.java | 17 +++++++---------- .../jbei/ice/lib/search/SearchController.java | 2 +- .../lib/search/filter/SearchFieldFactory.java | 4 ++++ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java index a49254532..b959d322c 100755 --- a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java +++ b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java @@ -35,7 +35,8 @@ import java.util.*; /** - * Apache Lucene full text library functionality in Hibernate + * Apache Lucene full text library functionality in Hibernate. + * Implemented as a singleton * * @author Hector Plahar */ @@ -67,14 +68,14 @@ protected BooleanQuery generateQueriesForType(FullTextSession fullTextSession, H for (String field : fields) { Query query; - if (type == QueryType.PHRASE) + if (type == QueryType.PHRASE) // phrase types are for quotes so slop is omitted query = qb.phrase().onField(field).sentence(term).createQuery(); else if (term.contains("*")) { - if (!field.equals("name")) + if (!SearchFieldFactory.isCommonField(field)) continue; query = qb.keyword().wildcard().onField(field).matching(term).createQuery(); } else - query = qb.keyword().fuzzy().withEditDistanceUpTo(1).onField(field).ignoreFieldBridge().matching( + query = qb.keyword().fuzzy().onField(field).ignoreFieldBridge().matching( term).createQuery(); booleanQuery.add(query, BooleanClause.Occur.SHOULD); @@ -93,9 +94,8 @@ else if (term.contains("*")) { // bio-safety level if (option != null) { TermContext levelContext = qb.keyword(); - Query biosafetyQuery = - levelContext.onField("bioSafetyLevel").ignoreFieldBridge() - .matching(option.getValue()).createQuery(); + Query biosafetyQuery = levelContext.onField("bioSafetyLevel").ignoreFieldBridge() + .matching(option.getValue()).createQuery(); booleanQuery.add(biosafetyQuery, BooleanClause.Occur.MUST); } } @@ -499,9 +499,6 @@ protected static String cleanQuery(String query) { cleanedQuery = cleanedQuery.endsWith("'") ? cleanedQuery.substring(0, cleanedQuery.length() - 1) : cleanedQuery; cleanedQuery = (cleanedQuery.endsWith("\\") ? cleanedQuery.substring(0, cleanedQuery.length() - 1) : cleanedQuery); -// if (cleanedQuery.startsWith("*") || cleanedQuery.startsWith("?")) { -// cleanedQuery = cleanedQuery.substring(1); -// } return cleanedQuery; } } diff --git a/src/main/java/org/jbei/ice/lib/search/SearchController.java b/src/main/java/org/jbei/ice/lib/search/SearchController.java index b3818e09e..36dbc7043 100755 --- a/src/main/java/org/jbei/ice/lib/search/SearchController.java +++ b/src/main/java/org/jbei/ice/lib/search/SearchController.java @@ -113,7 +113,7 @@ public SearchResults runLocalSearch(String userId, SearchQuery query) { try { blastResults = BlastPlus.runBlast(query.getBlastQuery()); } catch (BlastException e) { - return null; + Logger.error("Exception running blast " + e.getMessage()); } } diff --git a/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java b/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java index 3f3e06bbc..1beaba2ab 100644 --- a/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java +++ b/src/main/java/org/jbei/ice/lib/search/filter/SearchFieldFactory.java @@ -110,4 +110,8 @@ public static Class[] classesForTypes(List types) { } return classes; } + + public static boolean isCommonField(String field) { + return commonFields.contains(field); + } } From c6ebe9afb0c3dcdb823df2b69b0e6f74a5c9ecf0 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 25 Aug 2015 09:39:14 -0700 Subject: [PATCH 50/67] use relative paths --- src/main/webapp/scripts/services.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/scripts/services.js b/src/main/webapp/scripts/services.js index a75d2d4fc..7675e2cec 100755 --- a/src/main/webapp/scripts/services.js +++ b/src/main/webapp/scripts/services.js @@ -574,19 +574,19 @@ iceServices.factory('Settings', function ($resource) { rebuildLucene: { method: 'PUT', - url: '/rest/config/lucene', + url: 'rest/config/lucene', headers: {'X-ICE-Authentication-SessionId': sessionId} }, rebuildBlast: { method: 'PUT', - url: '/rest/config/blast', + url: 'rest/config/blast', headers: {'X-ICE-Authentication-SessionId': sessionId} }, version: { method: 'GET', - url: '/rest/config/version' + url: 'rest/config/version' } }); } @@ -815,7 +815,6 @@ iceServices.factory('Authentication', // checks if the session is valid isSessionValid: function () { -// console.log("check for valid session", who); var sid = $cookieStore.get('sessionId'); if (sid === undefined) { if ($location.path() !== '/login') From 56e478e68bc5c9b9a89e787d0f429eb99e40c02b Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 25 Aug 2015 10:55:32 -0700 Subject: [PATCH 51/67] do not use fuzzy searches for partnumber --- .../java/org/jbei/ice/lib/search/HibernateSearch.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java index b959d322c..568395f18 100755 --- a/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java +++ b/src/main/java/org/jbei/ice/lib/search/HibernateSearch.java @@ -74,9 +74,12 @@ else if (term.contains("*")) { if (!SearchFieldFactory.isCommonField(field)) continue; query = qb.keyword().wildcard().onField(field).matching(term).createQuery(); - } else - query = qb.keyword().fuzzy().onField(field).ignoreFieldBridge().matching( - term).createQuery(); + } else { + if (!"partNumber".equalsIgnoreCase(field)) + query = qb.keyword().fuzzy().onField(field).ignoreFieldBridge().matching(term).createQuery(); + else + query = qb.keyword().onField(field).ignoreFieldBridge().matching(term).createQuery(); + } booleanQuery.add(query, BooleanClause.Occur.SHOULD); } From 4b8a3d13a77b3160a8f8ad1d39d78da52f22c368 Mon Sep 17 00:00:00 2001 From: Hector Plahar Date: Tue, 25 Aug 2015 14:08:53 -0700 Subject: [PATCH 52/67] upgrading dependencies --- src/main/webapp/index.jsp | 12 +- src/main/webapp/scripts/controllers.js | 2 +- .../angular-file-upload.min.js | 7 +- .../angular-file-upload.min.js.map | 1 + .../angular-file-upload.min.map | 1 - .../lib/angular-slider/angular-slider.min.js | 452 ------- .../ui-bootstrap-tpls-0.13.0.min.js | 10 - .../ui-bootstrap-tpls-0.13.3.min.js | 10 + .../handsontable.full.min.css | 11 - .../handsontable.full.min.js | 27 - .../lib/handsontable-0.14.1/pikaday.js | 960 --------------- .../scripts/lib/handsontable-0.14.1/site.css | 42 - .../handsontable.full.min.css | 15 + .../handsontable.full.min.js | 43 + .../pikaday.css | 26 +- .../lib/handsontable-0.16.1/pikaday.js | 1080 +++++++++++++++++ 16 files changed, 1181 insertions(+), 1518 deletions(-) create mode 100755 src/main/webapp/scripts/lib/angular-file-upload/angular-file-upload.min.js.map delete mode 100755 src/main/webapp/scripts/lib/angular-file-upload/angular-file-upload.min.map delete mode 100644 src/main/webapp/scripts/lib/angular-slider/angular-slider.min.js delete mode 100644 src/main/webapp/scripts/lib/angular-ui/ui-bootstrap-tpls-0.13.0.min.js create mode 100644 src/main/webapp/scripts/lib/angular-ui/ui-bootstrap-tpls-0.13.3.min.js delete mode 100755 src/main/webapp/scripts/lib/handsontable-0.14.1/handsontable.full.min.css delete mode 100755 src/main/webapp/scripts/lib/handsontable-0.14.1/handsontable.full.min.js delete mode 100755 src/main/webapp/scripts/lib/handsontable-0.14.1/pikaday.js delete mode 100755 src/main/webapp/scripts/lib/handsontable-0.14.1/site.css create mode 100755 src/main/webapp/scripts/lib/handsontable-0.16.1/handsontable.full.min.css create mode 100755 src/main/webapp/scripts/lib/handsontable-0.16.1/handsontable.full.min.js rename src/main/webapp/scripts/lib/{handsontable-0.14.1 => handsontable-0.16.1}/pikaday.css (90%) create mode 100755 src/main/webapp/scripts/lib/handsontable-0.16.1/pikaday.js diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 5a6124cbd..a79225707 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -19,16 +19,14 @@ - + - - - - - - + + + + diff --git a/src/main/webapp/scripts/controllers.js b/src/main/webapp/scripts/controllers.js index 27731afec..6eccd793a 100755 --- a/src/main/webapp/scripts/controllers.js +++ b/src/main/webapp/scripts/controllers.js @@ -1,7 +1,7 @@ 'use strict'; var iceControllers = angular.module('iceApp.controllers', ['iceApp.services', 'ui.bootstrap', 'angularFileUpload', - 'vr.directives.slider', 'angularMoment']); + 'angularMoment']); iceControllers.controller('ActionMenuController', function ($stateParams, $scope, $window, $rootScope, $location, $cookieStore, Folders, Entry, WebOfRegistries, Files, Selection, Upload, FolderSelection) { $scope.editDisabled = $scope.addToDisabled = $scope.removeDisabled = $scope.moveToDisabled = $scope.deleteDisabled = true; diff --git a/src/main/webapp/scripts/lib/angular-file-upload/angular-file-upload.min.js b/src/main/webapp/scripts/lib/angular-file-upload/angular-file-upload.min.js index 93760c0b9..7242fd09e 100755 --- a/src/main/webapp/scripts/lib/angular-file-upload/angular-file-upload.min.js +++ b/src/main/webapp/scripts/lib/angular-file-upload/angular-file-upload.min.js @@ -1,6 +1,7 @@ /* - angular-file-upload v1.1.5 + angular-file-upload v2.1.1 https://github.com/nervgh/angular-file-upload */ -!function(a,b){return"function"==typeof define&&define.amd?(define("angular-file-upload",["angular"],function(a){return b(a)}),void 0):b(a)}("undefined"==typeof angular?null:angular,function(a){var b=a.module("angularFileUpload",[]);return b.value("fileUploaderOptions",{url:"/",alias:"file",headers:{},queue:[],progress:0,autoUpload:!1,removeAfterUpload:!1,method:"POST",filters:[],formData:[],queueLimit:Number.MAX_VALUE,withCredentials:!1}).factory("FileUploader",["fileUploaderOptions","$rootScope","$http","$window","$compile",function(b,c,d,e,f){function g(c){var d=a.copy(b);a.extend(this,d,c,{isUploading:!1,_nextIndex:0,_failFilterIndex:-1,_directives:{select:[],drop:[],over:[]}}),this.filters.unshift({name:"queueLimit",fn:this._queueLimitFilter}),this.filters.unshift({name:"folder",fn:this._folderFilter})}function h(b){var c=a.isElement(b),d=c?b.value:b,e=a.isString(d)?"FakePath":"Object",f="_createFrom"+e;this[f](d)}function i(b,c,d){var e=a.isElement(c),f=e?a.element(c):null,h=e?null:c;a.extend(this,{url:b.url,alias:b.alias,headers:a.copy(b.headers),formData:a.copy(b.formData),removeAfterUpload:b.removeAfterUpload,withCredentials:b.withCredentials,method:b.method},d,{uploader:b,file:new g.FileLikeObject(c),isReady:!1,isUploading:!1,isUploaded:!1,isSuccess:!1,isCancel:!1,isError:!1,progress:0,index:null,_file:h,_input:f}),f&&this._replaceNode(f)}function j(b){a.extend(this,b),this.uploader._directives[this.prop].push(this),this._saveLinks(),this.bind()}function k(){k.super_.apply(this,arguments),this.uploader.isHTML5||this.element.removeAttr("multiple"),this.element.prop("value",null)}function l(){l.super_.apply(this,arguments)}function m(){m.super_.apply(this,arguments)}return g.prototype.isHTML5=!(!e.File||!e.FormData),g.prototype.addToQueue=function(b,c,d){var e=this.isArrayLikeObject(b)?b:[b],f=this._getFilters(d),h=this.queue.length,i=[];a.forEach(e,function(a){var b=new g.FileLikeObject(a);if(this._isValidFile(b,f,c)){var d=new g.FileItem(this,a,c);i.push(d),this.queue.push(d),this._onAfterAddingFile(d)}else{var e=this.filters[this._failFilterIndex];this._onWhenAddingFileFailed(b,e,c)}},this),this.queue.length!==h&&(this._onAfterAddingAll(i),this.progress=this._getTotalProgress()),this._render(),this.autoUpload&&this.uploadAll()},g.prototype.removeFromQueue=function(a){var b=this.getIndexOfItem(a),c=this.queue[b];c.isUploading&&c.cancel(),this.queue.splice(b,1),c._destroy(),this.progress=this._getTotalProgress()},g.prototype.clearQueue=function(){for(;this.queue.length;)this.queue[0].remove();this.progress=0},g.prototype.uploadItem=function(a){var b=this.getIndexOfItem(a),c=this.queue[b],d=this.isHTML5?"_xhrTransport":"_iframeTransport";c._prepareToUploading(),this.isUploading||(this.isUploading=!0,this[d](c))},g.prototype.cancelItem=function(a){var b=this.getIndexOfItem(a),c=this.queue[b],d=this.isHTML5?"_xhr":"_form";c&&c.isUploading&&c[d].abort()},g.prototype.uploadAll=function(){var b=this.getNotUploadedItems().filter(function(a){return!a.isUploading});b.length&&(a.forEach(b,function(a){a._prepareToUploading()}),b[0].upload())},g.prototype.cancelAll=function(){var b=this.getNotUploadedItems();a.forEach(b,function(a){a.cancel()})},g.prototype.isFile=function(a){var b=e.File;return b&&a instanceof b},g.prototype.isFileLikeObject=function(a){return a instanceof g.FileLikeObject},g.prototype.isArrayLikeObject=function(b){return a.isObject(b)&&"length"in b},g.prototype.getIndexOfItem=function(b){return a.isNumber(b)?b:this.queue.indexOf(b)},g.prototype.getNotUploadedItems=function(){return this.queue.filter(function(a){return!a.isUploaded})},g.prototype.getReadyItems=function(){return this.queue.filter(function(a){return a.isReady&&!a.isUploading}).sort(function(a,b){return a.index-b.index})},g.prototype.destroy=function(){a.forEach(this._directives,function(b){a.forEach(this._directives[b],function(a){a.destroy()},this)},this)},g.prototype.onAfterAddingAll=function(){},g.prototype.onAfterAddingFile=function(){},g.prototype.onWhenAddingFileFailed=function(){},g.prototype.onBeforeUploadItem=function(){},g.prototype.onProgressItem=function(){},g.prototype.onProgressAll=function(){},g.prototype.onSuccessItem=function(){},g.prototype.onErrorItem=function(){},g.prototype.onCancelItem=function(){},g.prototype.onCompleteItem=function(){},g.prototype.onCompleteAll=function(){},g.prototype._getTotalProgress=function(a){if(this.removeAfterUpload)return a||0;var b=this.getNotUploadedItems().length,c=b?this.queue.length-b:this.queue.length,d=100/this.queue.length,e=(a||0)*d/100;return Math.round(c*d+e)},g.prototype._getFilters=function(b){if(a.isUndefined(b))return this.filters;if(a.isArray(b))return b;var c=b.match(/[^\s,]+/g);return this.filters.filter(function(a){return-1!==c.indexOf(a.name)},this)},g.prototype._render=function(){c.$$phase||c.$apply()},g.prototype._folderFilter=function(a){return!(!a.size&&!a.type)},g.prototype._queueLimitFilter=function(){return this.queue.length=200&&300>a||304===a},g.prototype._transformResponse=function(b,c){var e=this._headersGetter(c);return a.forEach(d.defaults.transformResponse,function(a){b=a(b,e)}),b},g.prototype._parseHeaders=function(b){var c,d,e,f={};return b?(a.forEach(b.split("\n"),function(a){e=a.indexOf(":"),c=a.slice(0,e).trim().toLowerCase(),d=a.slice(e+1).trim(),c&&(f[c]=f[c]?f[c]+", "+d:d)}),f):f},g.prototype._headersGetter=function(a){return function(b){return b?a[b.toLowerCase()]||null:a}},g.prototype._xhrTransport=function(b){var c=b._xhr=new XMLHttpRequest,d=new FormData,e=this;e._onBeforeUploadItem(b),a.forEach(b.formData,function(b){a.forEach(b,function(a,b){d.append(b,a)})}),d.append(b.alias,b._file,b.file.name),c.upload.onprogress=function(a){var c=Math.round(a.lengthComputable?100*a.loaded/a.total:0);e._onProgressItem(b,c)},c.onload=function(){var a=e._parseHeaders(c.getAllResponseHeaders()),d=e._transformResponse(c.response,a),f=e._isSuccessCode(c.status)?"Success":"Error",g="_on"+f+"Item";e[g](b,d,c.status,a),e._onCompleteItem(b,d,c.status,a)},c.onerror=function(){var a=e._parseHeaders(c.getAllResponseHeaders()),d=e._transformResponse(c.response,a);e._onErrorItem(b,d,c.status,a),e._onCompleteItem(b,d,c.status,a)},c.onabort=function(){var a=e._parseHeaders(c.getAllResponseHeaders()),d=e._transformResponse(c.response,a);e._onCancelItem(b,d,c.status,a),e._onCompleteItem(b,d,c.status,a)},c.open(b.method,b.url,!0),c.withCredentials=b.withCredentials,a.forEach(b.headers,function(a,b){c.setRequestHeader(b,a)}),c.send(d),this._render()},g.prototype._iframeTransport=function(b){var c=a.element('
'),d=a.element('