diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java index 99fe3595..7bf5dcd8 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/DocumentDao.java @@ -40,6 +40,19 @@ public class DocumentDao { return document.getId(); } + /** + * Returns an active document. + * + * @param id Document ID + * @return Document + */ + public Document getDocument(String id) { + EntityManager em = ThreadLocalContext.get().getEntityManager(); + Query q = em.createQuery("select d from Document d where d.id = :id and d.deleteDate is null"); + q.setParameter("id", id); + return (Document) q.getSingleResult(); + } + /** * Returns an active document. * @@ -74,7 +87,12 @@ public class DocumentDao { // Delete linked data q = em.createQuery("update File f set f.deleteDate = :dateNow where f.documentId = :documentId and f.deleteDate is null"); - q.setParameter("documentId", documentDb.getId()); + q.setParameter("documentId", id); + q.setParameter("dateNow", dateNow); + q.executeUpdate(); + + q = em.createQuery("update Share s set s.deleteDate = :dateNow where s.documentId = :documentId and s.deleteDate is null"); + q.setParameter("documentId", id); q.setParameter("dateNow", dateNow); q.executeUpdate(); } diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java index 162c258a..74b3a57a 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileDao.java @@ -64,12 +64,6 @@ public class FileDao { // Delete the file Date dateNow = new Date(); fileDb.setDeleteDate(dateNow); - - // Delete linked data - q = em.createQuery("update FileShare fs set fs.deleteDate = :dateNow where fs.fileId = :fileId and fs.deleteDate is null"); - q.setParameter("fileId", id); - q.setParameter("dateNow", dateNow); - q.executeUpdate(); } /** diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileShareDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileShareDao.java deleted file mode 100644 index 1bea51c2..00000000 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileShareDao.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.sismics.docs.core.dao.jpa; - -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import javax.persistence.EntityManager; -import javax.persistence.NoResultException; -import javax.persistence.Query; - -import com.sismics.docs.core.model.jpa.FileShare; -import com.sismics.util.context.ThreadLocalContext; - -/** - * File share DAO. - * - * @author bgamard - */ -public class FileShareDao { - /** - * Creates a new file share. - * - * @param fileShare File share - * @return New ID - * @throws Exception - */ - public String create(FileShare fileShare) { - // Create the UUID - fileShare.setId(UUID.randomUUID().toString()); - - // Create the file - EntityManager em = ThreadLocalContext.get().getEntityManager(); - fileShare.setCreateDate(new Date()); - em.persist(fileShare); - - return fileShare.getId(); - } - - /** - * Returns an active file share. - * - * @param id File ID - * @return Document - */ - public FileShare getFileShare(String id) { - EntityManager em = ThreadLocalContext.get().getEntityManager(); - Query q = em.createQuery("select fs from FileShare fs where fs.id = :id and fs.deleteDate is null"); - q.setParameter("id", id); - try { - return (FileShare) q.getSingleResult(); - } catch (NoResultException e) { - return null; - } - } - - /** - * Deletes a file share. - * - * @param id File ID - */ - public void delete(String id) { - EntityManager em = ThreadLocalContext.get().getEntityManager(); - - // Get the document - Query q = em.createQuery("select fs from FileShare fs where fs.id = :id and fs.deleteDate is null"); - q.setParameter("id", id); - FileShare fileShareDb = (FileShare) q.getSingleResult(); - - // Delete the document - Date dateNow = new Date(); - fileShareDb.setDeleteDate(dateNow); - } - - /** - * Gets a file share by its ID. - * - * @param id Document ID - * @return Document - */ - public FileShare getById(String id) { - EntityManager em = ThreadLocalContext.get().getEntityManager(); - try { - return em.find(FileShare.class, id); - } catch (NoResultException e) { - return null; - } - } - - /** - * Get file shares by file ID. - * - * @param fileId File ID - * @return List of file shares - */ - @SuppressWarnings("unchecked") - public List getByFileId(String fileId) { - EntityManager em = ThreadLocalContext.get().getEntityManager(); - Query q = em.createQuery("select fs from FileShare fs where fs.fileId = :fileId and fs.deleteDate is null"); - q.setParameter("fileId", fileId); - return q.getResultList(); - } -} diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/ShareDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/ShareDao.java new file mode 100644 index 00000000..32ecf291 --- /dev/null +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/ShareDao.java @@ -0,0 +1,113 @@ +package com.sismics.docs.core.dao.jpa; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; +import javax.persistence.Query; + +import com.sismics.docs.core.model.jpa.Document; +import com.sismics.docs.core.model.jpa.Share; +import com.sismics.util.context.ThreadLocalContext; + +/** + * Share DAO. + * + * @author bgamard + */ +public class ShareDao { + /** + * Creates a new share. + * + * @param share Share + * @return New ID + * @throws Exception + */ + public String create(Share share) { + // Create the UUID + share.setId(UUID.randomUUID().toString()); + + // Create the share + EntityManager em = ThreadLocalContext.get().getEntityManager(); + share.setCreateDate(new Date()); + em.persist(share); + + return share.getId(); + } + + /** + * Returns an active share. + * + * @param id Share ID + * @return Document + */ + public Share getShare(String id) { + EntityManager em = ThreadLocalContext.get().getEntityManager(); + Query q = em.createQuery("select s from Share s where s.id = :id and s.deleteDate is null"); + q.setParameter("id", id); + try { + return (Share) q.getSingleResult(); + } catch (NoResultException e) { + return null; + } + } + + /** + * Deletes a share. + * + * @param id Share ID + */ + public void delete(String id) { + EntityManager em = ThreadLocalContext.get().getEntityManager(); + + // Get the share + Query q = em.createQuery("select s from Share s where s.id = :id and s.deleteDate is null"); + q.setParameter("id", id); + Share shareDb = (Share) q.getSingleResult(); + + // Delete the share + Date dateNow = new Date(); + shareDb.setDeleteDate(dateNow); + } + + /** + * Get shares by document ID. + * + * @param documentId Document ID + * @return List of shares + */ + @SuppressWarnings("unchecked") + public List getByDocumentId(String documentId) { + EntityManager em = ThreadLocalContext.get().getEntityManager(); + Query q = em.createQuery("select s from Share s where s.documentId = :documentId and s.deleteDate is null"); + q.setParameter("documentId", documentId); + return q.getResultList(); + } + + /** + * Check if a document is visible. + * + * @param document Document to check for visibility + * @param userId Optional user trying to access the document + * @param shareId Optional share to access the document + * @return True if the document is visible + */ + public boolean checkVisibility(Document document, String userId, String shareId) { + // The user owns the document + if (document.getUserId().equals(userId)) { + return true; + } + + // The share is linked to the document + if (shareId != null) { + Share share = getShare(shareId); + if (share.getDocumentId().equals(document.getId())) { + return true; + } + } + + return false; + } +} diff --git a/docs-core/src/main/java/com/sismics/docs/core/model/jpa/FileShare.java b/docs-core/src/main/java/com/sismics/docs/core/model/jpa/FileShare.java deleted file mode 100644 index 032b2a3e..00000000 --- a/docs-core/src/main/java/com/sismics/docs/core/model/jpa/FileShare.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.sismics.docs.core.model.jpa; - -import com.google.common.base.Objects; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import java.util.Date; - -/** - * File share. - * - * @author bgamard - */ -@Entity -@Table(name = "T_FILESHARE") -public class FileShare { - /** - * File share ID. - */ - @Id - @Column(name = "FSH_ID_C", length = 36) - private String id; - - /** - * File ID. - */ - @Column(name = "FSH_IDFILE_C", nullable = false, length = 36) - private String fileId; - - /** - * Creation date. - */ - @Column(name = "FSH_CREATEDATE_D", nullable = false) - private Date createDate; - - /** - * Deletion date. - */ - @Column(name = "FSH_DELETEDATE_D") - private Date deleteDate; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getFileId() { - return fileId; - } - - public void setFileId(String fileId) { - this.fileId = fileId; - } - - public Date getCreateDate() { - return createDate; - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } - - public Date getDeleteDate() { - return deleteDate; - } - - public void setDeleteDate(Date deleteDate) { - this.deleteDate = deleteDate; - } - - @Override - public String toString() { - return Objects.toStringHelper(this) - .add("id", id) - .add("tagId", fileId) - .toString(); - } -} diff --git a/docs-core/src/main/java/com/sismics/docs/core/model/jpa/Share.java b/docs-core/src/main/java/com/sismics/docs/core/model/jpa/Share.java new file mode 100644 index 00000000..840f85b2 --- /dev/null +++ b/docs-core/src/main/java/com/sismics/docs/core/model/jpa/Share.java @@ -0,0 +1,144 @@ +package com.sismics.docs.core.model.jpa; + +import com.google.common.base.Objects; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Date; + +/** + * File share. + * + * @author bgamard + */ +@Entity +@Table(name = "T_SHARE") +public class Share { + /** + * Share ID. + */ + @Id + @Column(name = "SHA_ID_C", length = 36) + private String id; + + @Column(name = "SHA_NAME_C", length = 36) + private String name; + + /** + * Document ID. + */ + @Column(name = "SHA_IDDOCUMENT_C", nullable = false, length = 36) + private String documentId; + + /** + * Creation date. + */ + @Column(name = "SHA_CREATEDATE_D", nullable = false) + private Date createDate; + + /** + * Deletion date. + */ + @Column(name = "SHA_DELETEDATE_D") + private Date deleteDate; + + /** + * Getter of id. + * + * @return the id + */ + public String getId() { + return id; + } + + /** + * Setter of id. + * + * @param id id + */ + public void setId(String id) { + this.id = id; + } + + /** + * Getter of name. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Setter of name. + * + * @param name name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Getter of documentId. + * + * @return the documentId + */ + public String getDocumentId() { + return documentId; + } + + /** + * Setter of documentId. + * + * @param documentId documentId + */ + public void setDocumentId(String documentId) { + this.documentId = documentId; + } + + /** + * Getter of createDate. + * + * @return the createDate + */ + public Date getCreateDate() { + return createDate; + } + + /** + * Setter of createDate. + * + * @param createDate createDate + */ + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + /** + * Getter of deleteDate. + * + * @return the deleteDate + */ + public Date getDeleteDate() { + return deleteDate; + } + + /** + * Setter of deleteDate. + * + * @param deleteDate deleteDate + */ + public void setDeleteDate(Date deleteDate) { + this.deleteDate = deleteDate; + } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("id", id) + .add("tagId", documentId) + .toString(); + } +} diff --git a/docs-core/src/main/resources/META-INF/persistence.xml b/docs-core/src/main/resources/META-INF/persistence.xml index 2a985b15..eca250e4 100644 --- a/docs-core/src/main/resources/META-INF/persistence.xml +++ b/docs-core/src/main/resources/META-INF/persistence.xml @@ -15,6 +15,6 @@ com.sismics.docs.core.model.jpa.Document com.sismics.docs.core.model.jpa.Tag com.sismics.docs.core.model.jpa.DocumentTag - com.sismics.docs.core.model.jpa.FileShare + com.sismics.docs.core.model.jpa.Share \ No newline at end of file diff --git a/docs-core/src/main/resources/db/update/dbupdate-004-0.sql b/docs-core/src/main/resources/db/update/dbupdate-004-0.sql index 641e7b09..d0e47cd7 100644 --- a/docs-core/src/main/resources/db/update/dbupdate-004-0.sql +++ b/docs-core/src/main/resources/db/update/dbupdate-004-0.sql @@ -1 +1 @@ -create cached table T_FILESHARE ( FSH_ID_C varchar(36) not null, FSH_IDFILE_C varchar(36) not null, FSH_CREATEDATE_D datetime, FSH_DELETEDATE_D datetime, primary key (FSH_ID_C) ); \ No newline at end of file +create cached table T_SHARE ( SHA_ID_C varchar(36) not null, SHA_NAME_C varchar(36), SHA_IDDOCUMENT_C varchar(36) not null, SHA_CREATEDATE_D datetime, SHA_DELETEDATE_D datetime, primary key (SHA_ID_C) ); \ No newline at end of file diff --git a/docs-parent/TODO b/docs-parent/TODO index ec52e2e6..3d6dead4 100644 --- a/docs-parent/TODO +++ b/docs-parent/TODO @@ -1,2 +1 @@ -- Share a file with a link (client) -- Add a label to a file share \ No newline at end of file +- Share a document with a link (client) diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java index 5dcccb3a..f13d7141 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java @@ -1,12 +1,38 @@ package com.sismics.docs.rest.resource; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.persistence.NoResultException; +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +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.apache.commons.lang.StringUtils; +import org.codehaus.jettison.json.JSONException; +import org.codehaus.jettison.json.JSONObject; + import com.google.common.base.Strings; import com.sismics.docs.core.dao.jpa.DocumentDao; +import com.sismics.docs.core.dao.jpa.ShareDao; import com.sismics.docs.core.dao.jpa.TagDao; import com.sismics.docs.core.dao.jpa.criteria.DocumentCriteria; import com.sismics.docs.core.dao.jpa.dto.DocumentDto; import com.sismics.docs.core.dao.jpa.dto.TagDto; import com.sismics.docs.core.model.jpa.Document; +import com.sismics.docs.core.model.jpa.Share; import com.sismics.docs.core.model.jpa.Tag; import com.sismics.docs.core.util.jpa.PaginatedList; import com.sismics.docs.core.util.jpa.PaginatedLists; @@ -14,16 +40,6 @@ import com.sismics.docs.core.util.jpa.SortCriteria; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.util.ValidationUtil; -import org.apache.commons.lang.StringUtils; -import org.codehaus.jettison.json.JSONException; -import org.codehaus.jettison.json.JSONObject; - -import javax.persistence.NoResultException; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.text.MessageFormat; -import java.util.*; /** * Document REST resources. @@ -43,15 +59,20 @@ public class DocumentResource extends BaseResource { @Path("{id: [a-z0-9\\-]+}") @Produces(MediaType.APPLICATION_JSON) public Response get( - @PathParam("id") String id) throws JSONException { - if (!authenticate()) { - throw new ForbiddenClientException(); - } + @PathParam("id") String id, + @QueryParam("share") String shareId) throws JSONException { + authenticate(); DocumentDao documentDao = new DocumentDao(); + ShareDao shareDao = new ShareDao(); Document documentDb; try { - documentDb = documentDao.getDocument(id, principal.getId()); + documentDb = documentDao.getDocument(id); + + // Check document visibility + if (!shareDao.checkVisibility(documentDb, principal.getId(), shareId)) { + throw new ForbiddenClientException(); + } } catch (NoResultException e) { throw new ClientException("DocumentNotFound", MessageFormat.format("Document not found: {0}", id)); } @@ -62,7 +83,7 @@ public class DocumentResource extends BaseResource { document.put("description", documentDb.getDescription()); document.put("create_date", documentDb.getCreateDate().getTime()); - // Get tags + // Add tags TagDao tagDao = new TagDao(); List tagDtoList = tagDao.getByDocumentId(id); List tags = new ArrayList<>(); @@ -75,6 +96,17 @@ public class DocumentResource extends BaseResource { } document.put("tags", tags); + // Add shares + List shareDbList = shareDao.getByDocumentId(id); + List shareList = new ArrayList<>(); + for (Share shareDb : shareDbList) { + JSONObject share = new JSONObject(); + share.put("id", shareDb.getId()); + share.put("name", shareDb.getName()); + shareList.add(share); + } + document.put("shares", shareList); + return Response.ok().entity(document).build(); } diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java index 6c496711..704bd26f 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java @@ -28,10 +28,9 @@ import org.codehaus.jettison.json.JSONObject; import com.sismics.docs.core.dao.jpa.DocumentDao; import com.sismics.docs.core.dao.jpa.FileDao; -import com.sismics.docs.core.dao.jpa.FileShareDao; +import com.sismics.docs.core.dao.jpa.ShareDao; import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.File; -import com.sismics.docs.core.model.jpa.FileShare; import com.sismics.docs.core.util.DirectoryUtil; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; @@ -50,52 +49,6 @@ import com.sun.jersey.multipart.FormDataParam; */ @Path("/file") public class FileResource extends BaseResource { - /** - * Returns a file. - * - * @param id Document ID - * @return Response - * @throws JSONException - */ - @GET - @Path("{id: [a-z0-9\\-]+}") - @Produces(MediaType.APPLICATION_JSON) - public Response get( - @PathParam("id") String id) throws JSONException { - if (!authenticate()) { - throw new ForbiddenClientException(); - } - - FileDao fileDao = new FileDao(); - FileShareDao fileShareDao = new FileShareDao(); - DocumentDao documentDao = new DocumentDao(); - File fileDb; - try { - fileDb = fileDao.getFile(id); - documentDao.getDocument(fileDb.getDocumentId(), principal.getId()); - } catch (NoResultException e) { - throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", id)); - } - - JSONObject file = new JSONObject(); - file.put("id", fileDb.getId()); - file.put("mimetype", fileDb.getMimeType()); - file.put("document_id", fileDb.getDocumentId()); - file.put("create_date", fileDb.getCreateDate().getTime()); - - // Add file shares - List fileShareDbList = fileShareDao.getByFileId(id); - List fileShareList = new ArrayList<>(); - for (FileShare fileShareDb : fileShareDbList) { - JSONObject fileShare = new JSONObject(); - fileShare.put("id", fileShareDb.getId()); - fileShareList.add(fileShare); - } - file.put("shares", fileShareList); - - return Response.ok().entity(file).build(); - } - /** * Add a file to a document. * @@ -224,8 +177,15 @@ public class FileResource extends BaseResource { @Path("list") @Produces(MediaType.APPLICATION_JSON) public Response list( - @QueryParam("id") String documentId) throws JSONException { - if (!authenticate()) { + @QueryParam("id") String documentId, + @QueryParam("share") String shareId) throws JSONException { + authenticate(); + + // Check document visibility + DocumentDao documentDao = new DocumentDao(); + Document document = documentDao.getDocument(documentId); + ShareDao shareDao = new ShareDao(); + if (!shareDao.checkVisibility(document, principal.getId(), shareId)) { throw new ForbiddenClientException(); } @@ -297,21 +257,9 @@ public class FileResource extends BaseResource { @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response data( @PathParam("id") final String fileId, - @QueryParam("share") String fileShareId, + @QueryParam("share") String shareId, @QueryParam("thumbnail") boolean thumbnail) throws JSONException { - // Handle file sharing - FileShareDao fileShareDao = new FileShareDao(); - if (fileShareId != null) { - FileShare fileShare = fileShareDao.getFileShare(fileShareId); - if (fileShare == null) { - throw new ClientException("FileShareNotFound", "File share not found"); - } - if (!fileShare.getFileId().equals(fileId)) { - throw new ClientException("InvalidFile", "This file share is not linked to this file"); - } - } else if (!authenticate()) { - throw new ForbiddenClientException(); - } + authenticate(); // Get the file FileDao fileDao = new FileDao(); @@ -319,8 +267,12 @@ public class FileResource extends BaseResource { File file; try { file = fileDao.getFile(fileId); - if (fileShareId == null) { - documentDao.getDocument(file.getDocumentId(), principal.getId()); + Document document = documentDao.getDocument(file.getDocumentId()); + + // Check document visibility + ShareDao shareDao = new ShareDao(); + if (!shareDao.checkVisibility(document, principal.getId(), shareId)) { + throw new ForbiddenClientException(); } } catch (NoResultException e) { throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", fileId)); diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileShareResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/ShareResource.java similarity index 53% rename from docs-web/src/main/java/com/sismics/docs/rest/resource/FileShareResource.java rename to docs-web/src/main/java/com/sismics/docs/rest/resource/ShareResource.java index 4cb5022f..c6e421b4 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileShareResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/ShareResource.java @@ -17,67 +17,65 @@ import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import com.sismics.docs.core.dao.jpa.DocumentDao; -import com.sismics.docs.core.dao.jpa.FileDao; -import com.sismics.docs.core.dao.jpa.FileShareDao; -import com.sismics.docs.core.model.jpa.File; -import com.sismics.docs.core.model.jpa.FileShare; +import com.sismics.docs.core.dao.jpa.ShareDao; +import com.sismics.docs.core.model.jpa.Share; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.util.ValidationUtil; /** - * File share REST resources. + * Share REST resources. * * @author bgamard */ -@Path("/fileshare") -public class FileShareResource extends BaseResource { +@Path("/share") +public class ShareResource extends BaseResource { /** - * Add a file share to a file. + * Add a share to a document. * - * @param fileId File ID - * @param fileBodyPart File to add + * @param documentId Document ID * @return Response * @throws JSONException */ @PUT @Produces(MediaType.APPLICATION_JSON) public Response add( - @FormParam("id") String fileId) throws JSONException { + @FormParam("id") String documentId, + @FormParam("name") String name) throws JSONException { if (!authenticate()) { throw new ForbiddenClientException(); } // Validate input data - ValidationUtil.validateRequired(fileId, "id"); + ValidationUtil.validateRequired(documentId, "id"); + name = ValidationUtil.validateLength(name, "name", 1, 36, true); - // Get the file - FileDao fileDao = new FileDao(); + // Get the document DocumentDao documentDao = new DocumentDao(); try { - File file = fileDao.getFile(fileId); - documentDao.getDocument(file.getDocumentId(), principal.getId()); + documentDao.getDocument(documentId, principal.getId()); } catch (NoResultException e) { - throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", fileId)); + throw new ClientException("DocumentNotFound", MessageFormat.format("Document not found: {0}", documentId)); } - // Create the file share - FileShareDao fileShareDao = new FileShareDao(); - FileShare fileShare = new FileShare(); - fileShare.setFileId(fileId); - fileShareDao.create(fileShare); + // Create the share + ShareDao shareDao = new ShareDao(); + Share share = new Share(); + share.setDocumentId(documentId); + share.setName(name); + shareDao.create(share); // Always return ok JSONObject response = new JSONObject(); response.put("status", "ok"); - response.put("id", fileShare.getId()); + response.put("id", share.getId()); return Response.ok().entity(response).build(); } /** - * Deletes a file share. + * Deletes a share. * - * @param id File share ID + * @param id Share ID * @return Response * @throws JSONException */ @@ -90,21 +88,19 @@ public class FileShareResource extends BaseResource { throw new ForbiddenClientException(); } - // Get the file share - FileShareDao fileShareDao = new FileShareDao(); - FileDao fileDao = new FileDao(); + // Get the share + ShareDao shareDao = new ShareDao(); DocumentDao documentDao = new DocumentDao(); - FileShare fileShare; + Share share; try { - fileShare = fileShareDao.getFileShare(id); - File file = fileDao.getFile(fileShare.getFileId()); - documentDao.getDocument(file.getDocumentId(), principal.getId()); + share = shareDao.getShare(id); + documentDao.getDocument(share.getDocumentId(), principal.getId()); } catch (NoResultException e) { - throw new ClientException("FileShareNotFound", MessageFormat.format("File share not found: {0}", id)); + throw new ClientException("ShareNotFound", MessageFormat.format("Share not found: {0}", id)); } - // Delete the file share - fileShareDao.delete(fileShare.getId()); + // Delete the share + shareDao.delete(share.getId()); // Always return ok JSONObject response = new JSONObject(); diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java index 4f5fa245..1a71e53a 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java @@ -1,22 +1,24 @@ package com.sismics.docs.rest; +import java.io.BufferedInputStream; +import java.io.InputStream; + +import javax.ws.rs.core.MediaType; + +import junit.framework.Assert; + +import org.codehaus.jettison.json.JSONArray; +import org.codehaus.jettison.json.JSONObject; +import org.junit.Test; + import com.google.common.io.ByteStreams; import com.sismics.docs.rest.filter.CookieAuthenticationFilter; -import com.sismics.util.mime.MimeType; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.ClientResponse.Status; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.core.util.MultivaluedMapImpl; import com.sun.jersey.multipart.FormDataBodyPart; import com.sun.jersey.multipart.FormDataMultiPart; -import junit.framework.Assert; -import org.codehaus.jettison.json.JSONArray; -import org.codehaus.jettison.json.JSONObject; -import org.junit.Test; - -import javax.ws.rs.core.MediaType; -import java.io.BufferedInputStream; -import java.io.InputStream; /** * Exhaustive test of the file resource. @@ -76,15 +78,6 @@ public class TestFileResource extends BaseJerseyTest { json = response.getEntity(JSONObject.class); String file2Id = json.getString("id"); - // Get the file - fileResource = resource().path("/file/" + file1Id); - fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); - response = fileResource.get(ClientResponse.class); - json = response.getEntity(JSONObject.class); - Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); - Assert.assertEquals(MimeType.IMAGE_JPEG, json.getString("mimetype")); - Assert.assertEquals(file1Id, json.getString("id")); - // Get the file data fileResource = resource().path("/file/" + file1Id + "/data"); fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestFileShareResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestShareResource.java similarity index 63% rename from docs-web/src/test/java/com/sismics/docs/rest/TestFileShareResource.java rename to docs-web/src/test/java/com/sismics/docs/rest/TestShareResource.java index 2864bb40..a4cbca01 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestFileShareResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestShareResource.java @@ -7,6 +7,7 @@ import javax.ws.rs.core.MediaType; import junit.framework.Assert; +import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONObject; import org.junit.Test; @@ -20,25 +21,25 @@ import com.sun.jersey.multipart.FormDataBodyPart; import com.sun.jersey.multipart.FormDataMultiPart; /** - * Exhaustive test of the file share resource. + * Exhaustive test of the share resource. * * @author bgamard */ -public class TestFileShareResource extends BaseJerseyTest { +public class TestShareResource extends BaseJerseyTest { /** - * Test the file share resource. + * Test the share resource. * * @throws Exception */ @Test - public void testFileShareResource() throws Exception { - // Login fileshare1 - clientUtil.createUser("fileshare1"); - String fileShare1AuthenticationToken = clientUtil.login("fileshare1"); + public void testShareResource() throws Exception { + // Login share1 + clientUtil.createUser("share1"); + String share1AuthenticationToken = clientUtil.login("share1"); // Create a document WebResource documentResource = resource().path("/document"); - documentResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + documentResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); MultivaluedMapImpl postParams = new MultivaluedMapImpl(); postParams.add("title", "File test document 1"); ClientResponse response = documentResource.put(ClientResponse.class, postParams); @@ -49,7 +50,7 @@ public class TestFileShareResource extends BaseJerseyTest { // Add a file WebResource fileResource = resource().path("/file"); - fileResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + fileResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); FormDataMultiPart form = new FormDataMultiPart(); InputStream file = this.getClass().getResourceAsStream("/file/PIA00452.jpg"); FormDataBodyPart fdp = new FormDataBodyPart("file", @@ -62,40 +63,54 @@ public class TestFileShareResource extends BaseJerseyTest { json = response.getEntity(JSONObject.class); String file1Id = json.getString("id"); - // Share this file - WebResource fileShareResource = resource().path("/fileshare"); - fileShareResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + // Share this document + WebResource fileShareResource = resource().path("/share"); + fileShareResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); postParams = new MultivaluedMapImpl(); - postParams.add("id", file1Id); + postParams.add("id", document1Id); + postParams.add("name", "4 All"); response = fileShareResource.put(ClientResponse.class, postParams); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); json = response.getEntity(JSONObject.class); - String fileShare1Id = json.getString("id"); + String share1Id = json.getString("id"); + + // Get the document anonymously + documentResource = resource().path("/document/" + document1Id); + MultivaluedMapImpl getParams = new MultivaluedMapImpl(); + getParams.putSingle("share", share1Id); + response = documentResource.queryParams(getParams).get(ClientResponse.class); + json = response.getEntity(JSONObject.class); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + Assert.assertEquals(document1Id, json.getString("id")); + Assert.assertEquals(1, json.getJSONArray("shares").length()); + Assert.assertEquals(share1Id, json.getJSONArray("shares").getJSONObject(0).getString("id")); + Assert.assertEquals("4 All", json.getJSONArray("shares").getJSONObject(0).getString("name")); + // Get all files from this document anonymously + fileResource = resource().path("/file/list"); + getParams = new MultivaluedMapImpl(); + getParams.putSingle("id", document1Id); + getParams.putSingle("share", share1Id); + response = fileResource.queryParams(getParams).get(ClientResponse.class); + json = response.getEntity(JSONObject.class); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + JSONArray files = json.getJSONArray("files"); + Assert.assertEquals(1, files.length()); + // Get the file data anonymously fileResource = resource().path("/file/" + file1Id + "/data"); - MultivaluedMapImpl getParams = new MultivaluedMapImpl(); + getParams = new MultivaluedMapImpl(); getParams.putSingle("thumbnail", false); - getParams.putSingle("share", fileShare1Id); + getParams.putSingle("share", share1Id); response = fileResource.queryParams(getParams).get(ClientResponse.class); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); InputStream is = response.getEntityInputStream(); byte[] fileBytes = ByteStreams.toByteArray(is); Assert.assertEquals(163510, fileBytes.length); - // Get the file - fileResource = resource().path("/file/" + file1Id); - fileResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); - response = fileResource.get(ClientResponse.class); - json = response.getEntity(JSONObject.class); - Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); - Assert.assertEquals(file1Id, json.getString("id")); - Assert.assertEquals(1, json.getJSONArray("shares").length()); - Assert.assertEquals(fileShare1Id, json.getJSONArray("shares").getJSONObject(0).getString("id")); - // Deletes the share - fileShareResource = resource().path("/fileshare/" + fileShare1Id); - fileShareResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + fileShareResource = resource().path("/share/" + share1Id); + fileShareResource.addFilter(new CookieAuthenticationFilter(share1AuthenticationToken)); response = fileShareResource.delete(ClientResponse.class); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); json = response.getEntity(JSONObject.class);