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 d2694bda..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 @@ -56,12 +56,12 @@ public class FileDao { public void delete(String id) { EntityManager em = ThreadLocalContext.get().getEntityManager(); - // Get the document + // Get the file Query q = em.createQuery("select f from File f where f.id = :id and f.deleteDate is null"); q.setParameter("id", id); File fileDb = (File) q.getSingleResult(); - // Delete the document + // Delete the file Date dateNow = new Date(); fileDb.setDeleteDate(dateNow); } @@ -69,8 +69,8 @@ public class FileDao { /** * Gets a file by its ID. * - * @param id Document ID - * @return Document + * @param id File ID + * @return File */ public File getById(String id) { EntityManager em = ThreadLocalContext.get().getEntityManager(); 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 new file mode 100644 index 00000000..8ac9f3b0 --- /dev/null +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/FileShareDao.java @@ -0,0 +1,98 @@ +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); + return (FileShare) q.getSingleResult(); + } + + /** + * 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-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 8a2e78c9..3546ea3a 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 @@ -54,10 +54,11 @@ public class FileResource extends BaseResource { } FileDao fileDao = new FileDao(); + DocumentDao documentDao = new DocumentDao(); File fileDb; try { fileDb = fileDao.getFile(id); - // TODO Check that the current user owns the document linked to this file + documentDao.getDocument(fileDb.getDocumentId(), principal.getId()); } catch (NoResultException e) { throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", id)); } @@ -241,15 +242,17 @@ public class FileResource extends BaseResource { // Get the file FileDao fileDao = new FileDao(); + DocumentDao documentDao = new DocumentDao(); File file; try { file = fileDao.getFile(id); - // TODO Check that the current user owns the document linked to this file + documentDao.getDocument(file.getDocumentId(), principal.getId()); } catch (NoResultException e) { throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", id)); } - // Delete the document + // Delete the file + // TODO Delete the file from storage too fileDao.delete(file.getId()); // Always return ok @@ -277,10 +280,11 @@ public class FileResource extends BaseResource { // Get the file FileDao fileDao = new FileDao(); + DocumentDao documentDao = new DocumentDao(); File file; try { file = fileDao.getFile(id); - // TODO Check that the current user owns the document linked to this file + documentDao.getDocument(file.getDocumentId(), principal.getId()); } catch (NoResultException e) { throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", id)); } 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/FileShareResource.java index 96edc56e..4cb5022f 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/FileShareResource.java @@ -1,7 +1,11 @@ package com.sismics.docs.rest.resource; -import javax.ws.rs.Consumes; + +import java.text.MessageFormat; + +import javax.persistence.NoResultException; import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -12,16 +16,21 @@ import javax.ws.rs.core.Response; 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.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.util.ValidationUtil; -import com.sun.jersey.multipart.FormDataParam; /** * File share REST resources. * * @author bgamard */ -@Path("/share") +@Path("/fileshare") public class FileShareResource extends BaseResource { /** * Add a file share to a file. @@ -32,10 +41,9 @@ public class FileShareResource extends BaseResource { * @throws JSONException */ @PUT - @Consumes("multipart/form-data") @Produces(MediaType.APPLICATION_JSON) public Response add( - @FormDataParam("id") String fileId) throws JSONException { + @FormParam("id") String fileId) throws JSONException { if (!authenticate()) { throw new ForbiddenClientException(); } @@ -44,19 +52,32 @@ public class FileShareResource extends BaseResource { ValidationUtil.validateRequired(fileId, "id"); // Get the file - // TODO Not implemented + FileDao fileDao = new FileDao(); + DocumentDao documentDao = new DocumentDao(); + try { + File file = fileDao.getFile(fileId); + documentDao.getDocument(file.getDocumentId(), principal.getId()); + } catch (NoResultException e) { + throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", fileId)); + } + + // Create the file share + FileShareDao fileShareDao = new FileShareDao(); + FileShare fileShare = new FileShare(); + fileShare.setFileId(fileId); + fileShareDao.create(fileShare); // Always return ok JSONObject response = new JSONObject(); response.put("status", "ok"); - response.put("id", fileId); + response.put("id", fileShare.getId()); return Response.ok().entity(response).build(); } /** * Deletes a file share. * - * @param id File shqre ID + * @param id File share ID * @return Response * @throws JSONException */ @@ -69,20 +90,22 @@ public class FileShareResource extends BaseResource { throw new ForbiddenClientException(); } - // Get the file shqre -// FileShareDao fileShareDao = new FileShareDao(); -// FileShare fileShare; -// try { -// fileShare = fileShareDao.getFileShare(id); -// } catch (NoResultException e) { -// throw new ClientException("FileNotFound", MessageFormat.format("File not found: {0}", id)); -// } -// -// // Delete the file share -// fileShareDao.delete(fileShare.getId()); - - // TODO Not implemented + // Get the file share + FileShareDao fileShareDao = new FileShareDao(); + FileDao fileDao = new FileDao(); + DocumentDao documentDao = new DocumentDao(); + FileShare fileShare; + try { + fileShare = fileShareDao.getFileShare(id); + File file = fileDao.getFile(fileShare.getFileId()); + documentDao.getDocument(file.getDocumentId(), principal.getId()); + } catch (NoResultException e) { + throw new ClientException("FileShareNotFound", MessageFormat.format("File share not found: {0}", id)); + } + // Delete the file share + fileShareDao.delete(fileShare.getId()); + // Always return ok JSONObject response = new JSONObject(); response.put("status", "ok"); 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 111ecd1b..4f5fa245 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 @@ -19,13 +19,13 @@ import java.io.BufferedInputStream; import java.io.InputStream; /** - * Exhaustive test of the document resource. + * Exhaustive test of the file resource. * * @author bgamard */ public class TestFileResource extends BaseJerseyTest { /** - * Test the document resource. + * Test the file resource. * * @throws Exception */ @@ -144,9 +144,9 @@ public class TestFileResource extends BaseJerseyTest { Assert.assertEquals(file1Id, files.getJSONObject(1).getString("id")); // Deletes a file - documentResource = resource().path("/file/" + file1Id); - documentResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); - response = documentResource.delete(ClientResponse.class); + fileResource = resource().path("/file/" + file1Id); + fileResource.addFilter(new CookieAuthenticationFilter(file1AuthenticationToken)); + response = fileResource.delete(ClientResponse.class); Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); json = response.getEntity(JSONObject.class); Assert.assertEquals("ok", json.getString("status")); diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestFileShareResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestFileShareResource.java new file mode 100644 index 00000000..28084760 --- /dev/null +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestFileShareResource.java @@ -0,0 +1,83 @@ +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.JSONObject; +import org.junit.Test; + +import com.sismics.docs.rest.filter.CookieAuthenticationFilter; +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; + +/** + * Exhaustive test of the file share resource. + * + * @author bgamard + */ +public class TestFileShareResource extends BaseJerseyTest { + /** + * Test the file share resource. + * + * @throws Exception + */ + @Test + public void testFileShareResource() throws Exception { + // Login fileshare1 + clientUtil.createUser("fileshare1"); + String fileShare1AuthenticationToken = clientUtil.login("fileshare1"); + + // Create a document + WebResource documentResource = resource().path("/document"); + documentResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + MultivaluedMapImpl postParams = new MultivaluedMapImpl(); + postParams.add("title", "File test document 1"); + ClientResponse response = documentResource.put(ClientResponse.class, postParams); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + JSONObject json = response.getEntity(JSONObject.class); + String document1Id = json.optString("id"); + Assert.assertNotNull(document1Id); + + // Add a file + WebResource fileResource = resource().path("/file"); + fileResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + FormDataMultiPart form = new FormDataMultiPart(); + InputStream file = this.getClass().getResourceAsStream("/file/PIA00452.jpg"); + FormDataBodyPart fdp = new FormDataBodyPart("file", + new BufferedInputStream(file), + MediaType.APPLICATION_OCTET_STREAM_TYPE); + form.bodyPart(fdp); + form.field("id", document1Id); + response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + json = response.getEntity(JSONObject.class); + String file1Id = json.getString("id"); + + // Share this file + WebResource fileShareResource = resource().path("/fileshare"); + fileShareResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + postParams = new MultivaluedMapImpl(); + postParams.add("id", file1Id); + response = fileShareResource.put(ClientResponse.class, postParams); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + json = response.getEntity(JSONObject.class); + String fileShare1Id = json.getString("id"); + + // Deletes the share + fileShareResource = resource().path("/fileshare/" + fileShare1Id); + fileShareResource.addFilter(new CookieAuthenticationFilter(fileShare1AuthenticationToken)); + response = fileShareResource.delete(ClientResponse.class); + Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus())); + json = response.getEntity(JSONObject.class); + Assert.assertEquals("ok", json.getString("status")); + + } +} \ No newline at end of file