From c2a2e9f585aa334ce95b66365ef3eb31fdb556ca Mon Sep 17 00:00:00 2001 From: jendib Date: Mon, 14 Mar 2016 01:39:29 +0100 Subject: [PATCH] DAO/event refactoring --- .../docs/core/dao/jpa/DocumentDao.java | 45 +++++++------------ .../docs/core/dao/jpa/VocabularyDao.java | 2 +- .../docs/core/dao/lucene/LuceneDao.java | 21 +++------ .../core/event/DocumentDeletedAsyncEvent.java | 25 +++-------- .../core/event/DocumentUpdatedAsyncEvent.java | 25 +++-------- .../core/event/FileCreatedAsyncEvent.java | 15 +++---- .../core/event/FileDeletedAsyncEvent.java | 10 ----- .../async/DocumentDeletedAsyncListener.java | 2 +- .../async/DocumentUpdatedAsyncListener.java | 16 ++++--- .../async/FileCreatedAsyncListener.java | 4 +- .../com/sismics/docs/core/util/FileUtil.java | 13 +++--- .../com/sismics/docs/core/util/PdfUtil.java | 19 ++++++-- .../sismics/docs/core/util/TestFileUtil.java | 2 +- .../docs/rest/resource/DocumentResource.java | 42 ++++++++--------- .../docs/rest/resource/FileResource.java | 35 ++++++--------- .../docs/rest/resource/UserResource.java | 4 +- .../sismics/docs/rest/TestAclResource.java | 4 +- .../docs/rest/TestDocumentResource.java | 2 +- 18 files changed, 119 insertions(+), 167 deletions(-) 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 f721824e..2221f532 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 @@ -57,7 +57,7 @@ public class DocumentDao { } /** - * Returns the list of all documents. + * Returns the list of all active documents. * * @return List of documents */ @@ -69,7 +69,7 @@ public class DocumentDao { } /** - * Returns the list of all documents from a user. + * Returns the list of all active documents from a user. * * @param userId User ID * @return List of documents @@ -83,21 +83,28 @@ public class DocumentDao { } /** - * Returns an active document. + * Returns an active document with permission checking. * * @param id Document ID + * @param perm Permission needed + * @param userId User ID * @return Document */ - public DocumentDto getDocument(String id) { + public DocumentDto getDocument(String id, PermType perm, String userId) { EntityManager em = ThreadLocalContext.get().getEntityManager(); StringBuilder sb = new StringBuilder("select d.DOC_ID_C, d.DOC_TITLE_C, d.DOC_DESCRIPTION_C, d.DOC_SUBJECT_C, d.DOC_IDENTIFIER_C, d.DOC_PUBLISHER_C, d.DOC_FORMAT_C, d.DOC_SOURCE_C, d.DOC_TYPE_C, d.DOC_COVERAGE_C, d.DOC_RIGHTS_C, d.DOC_CREATEDATE_D, d.DOC_LANGUAGE_C, "); sb.append(" (select count(s.SHA_ID_C) from T_SHARE s, T_ACL ac where ac.ACL_SOURCEID_C = d.DOC_ID_C and ac.ACL_TARGETID_C = s.SHA_ID_C and ac.ACL_DELETEDATE_D is null and s.SHA_DELETEDATE_D is null), "); sb.append(" (select count(f.FIL_ID_C) from T_FILE f where f.FIL_DELETEDATE_D is null and f.FIL_IDDOC_C = d.DOC_ID_C), "); sb.append(" u.USE_USERNAME_C "); sb.append(" from T_DOCUMENT d, T_USER u "); + sb.append(" join T_ACL a on a.ACL_SOURCEID_C = d.DOC_ID_C and a.ACL_TARGETID_C = :userId and a.ACL_PERM_C = :perm and a.ACL_DELETEDATE_D is null "); sb.append(" where d.DOC_IDUSER_C = u.USE_ID_C and d.DOC_ID_C = :id and d.DOC_DELETEDATE_D is null "); + Query q = em.createNativeQuery(sb.toString()); q.setParameter("id", id); + q.setParameter("perm", perm.name()); + q.setParameter("userId", userId); + Object[] o = null; try { o = (Object[]) q.getSingleResult(); @@ -126,30 +133,6 @@ public class DocumentDao { return documentDto; } - /** - * Returns an active document. - * - * @param id Document ID - * @param perm Permission needed - * @param userId User ID - * @return Document - */ - public Document getDocument(String id, PermType perm, String userId) { - EntityManager em = ThreadLocalContext.get().getEntityManager(); - StringBuilder sb = new StringBuilder("select d.* from T_DOCUMENT d "); - sb.append(" join T_ACL a on a.ACL_SOURCEID_C = d.DOC_ID_C and a.ACL_TARGETID_C = :userId and a.ACL_PERM_C = :perm and a.ACL_DELETEDATE_D is null "); - sb.append(" where d.DOC_ID_C = :id and d.DOC_DELETEDATE_D is null"); - Query q = em.createNativeQuery(sb.toString(), Document.class); - q.setParameter("id", id); - q.setParameter("perm", perm.name()); - q.setParameter("userId", userId); - try { - return (Document) q.getSingleResult(); - } catch (NoResultException e) { - return null; - } - } - /** * Deletes a document. * @@ -194,15 +177,17 @@ public class DocumentDao { } /** - * Gets a document by its ID. + * Gets an active document by its ID. * * @param id Document ID * @return Document */ public Document getById(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); try { - return em.find(Document.class, id); + return (Document) q.getSingleResult(); } catch (NoResultException e) { return null; } diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/VocabularyDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/VocabularyDao.java index fe500a26..710edb21 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/VocabularyDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/VocabularyDao.java @@ -35,7 +35,7 @@ public class VocabularyDao { } /** - * Get all vocabulary entries sharing a single name + * Get all vocabulary entries sharing a single name. * * @param name Name * @return Vocabulary entries diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java index e144a559..104121e0 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/lucene/LuceneDao.java @@ -1,9 +1,7 @@ package com.sismics.docs.core.dao.lucene; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import org.apache.lucene.analysis.standard.StandardAnalyzer; @@ -46,16 +44,14 @@ public class LuceneDao { indexWriter.deleteAll(); // Add all documents - Map documentMap = new HashMap<>(); for (Document document : documentList) { org.apache.lucene.document.Document luceneDocument = getDocumentFromDocument(document); indexWriter.addDocument(luceneDocument); - documentMap.put(document.getId(), document); } // Add all files for (File file : fileList) { - org.apache.lucene.document.Document luceneDocument = getDocumentFromFile(file, documentMap.get(file.getDocumentId())); + org.apache.lucene.document.Document luceneDocument = getDocumentFromFile(file); indexWriter.addDocument(luceneDocument); } } @@ -81,13 +77,12 @@ public class LuceneDao { * Add file to the index. * * @param file File to add - * @param document Document linked to the file */ - public void createFile(final File file, final Document document) { + public void createFile(final File file) { LuceneUtil.handle(new LuceneRunnable() { @Override public void run(IndexWriter indexWriter) throws Exception { - org.apache.lucene.document.Document luceneDocument = getDocumentFromFile(file, document); + org.apache.lucene.document.Document luceneDocument = getDocumentFromFile(file); indexWriter.addDocument(luceneDocument); } }); @@ -112,13 +107,12 @@ public class LuceneDao { * Update file index. * * @param file Updated file - * @param document Document linked to the file */ - public void updateFile(final File file, final Document document) { + public void updateFile(final File file) { LuceneUtil.handle(new LuceneRunnable() { @Override public void run(IndexWriter indexWriter) throws Exception { - org.apache.lucene.document.Document luceneDocument = getDocumentFromFile(file, document); + org.apache.lucene.document.Document luceneDocument = getDocumentFromFile(file); indexWriter.updateDocument(new Term("id", file.getId()), luceneDocument); } }); @@ -200,7 +194,7 @@ public class LuceneDao { /** * Build Lucene document from database document. * - * @param document Document + * @param documentDto Document * @return Document */ private org.apache.lucene.document.Document getDocumentFromDocument(Document document) { @@ -243,10 +237,9 @@ public class LuceneDao { * Build Lucene document from file. * * @param file File - * @param document Document linked to the file * @return Document */ - private org.apache.lucene.document.Document getDocumentFromFile(File file, Document document) { + private org.apache.lucene.document.Document getDocumentFromFile(File file) { org.apache.lucene.document.Document luceneDocument = new org.apache.lucene.document.Document(); luceneDocument.add(new StringField("id", file.getId(), Field.Store.YES)); luceneDocument.add(new StringField("doctype", "file", Field.Store.YES)); diff --git a/docs-core/src/main/java/com/sismics/docs/core/event/DocumentDeletedAsyncEvent.java b/docs-core/src/main/java/com/sismics/docs/core/event/DocumentDeletedAsyncEvent.java index 2ea7dd69..6c314662 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/event/DocumentDeletedAsyncEvent.java +++ b/docs-core/src/main/java/com/sismics/docs/core/event/DocumentDeletedAsyncEvent.java @@ -1,7 +1,6 @@ package com.sismics.docs.core.event; import com.google.common.base.MoreObjects; -import com.sismics.docs.core.model.jpa.Document; /** * Document deleted event. @@ -10,32 +9,22 @@ import com.sismics.docs.core.model.jpa.Document; */ public class DocumentDeletedAsyncEvent extends UserEvent { /** - * Created document. + * Document ID. */ - private Document document; + private String documentId; - /** - * Getter of document. - * - * @return the document - */ - public Document getDocument() { - return document; + public String getDocumentId() { + return documentId; } - /** - * Setter of document. - * - * @param document document - */ - public void setDocument(Document document) { - this.document = document; + public void setDocumentId(String documentId) { + this.documentId = documentId; } @Override public String toString() { return MoreObjects.toStringHelper(this) - .add("document", document) + .add("documentId", documentId) .toString(); } } \ No newline at end of file diff --git a/docs-core/src/main/java/com/sismics/docs/core/event/DocumentUpdatedAsyncEvent.java b/docs-core/src/main/java/com/sismics/docs/core/event/DocumentUpdatedAsyncEvent.java index da82cc1e..f5e2ef74 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/event/DocumentUpdatedAsyncEvent.java +++ b/docs-core/src/main/java/com/sismics/docs/core/event/DocumentUpdatedAsyncEvent.java @@ -1,7 +1,6 @@ package com.sismics.docs.core.event; import com.google.common.base.MoreObjects; -import com.sismics.docs.core.model.jpa.Document; /** * Document updated event. @@ -10,32 +9,22 @@ import com.sismics.docs.core.model.jpa.Document; */ public class DocumentUpdatedAsyncEvent extends UserEvent { /** - * Created document. + * Document ID. */ - private Document document; + private String documentId; - /** - * Getter of document. - * - * @return the document - */ - public Document getDocument() { - return document; + public String getDocumentId() { + return documentId; } - /** - * Setter of document. - * - * @param document document - */ - public void setDocument(Document document) { - this.document = document; + public void setDocumentId(String documentId) { + this.documentId = documentId; } @Override public String toString() { return MoreObjects.toStringHelper(this) - .add("document", document) + .add("documentId", documentId) .toString(); } } \ No newline at end of file diff --git a/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java b/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java index 5dbf7d30..c6cfe07f 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java +++ b/docs-core/src/main/java/com/sismics/docs/core/event/FileCreatedAsyncEvent.java @@ -3,7 +3,6 @@ package com.sismics.docs.core.event; import java.io.InputStream; import com.google.common.base.MoreObjects; -import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.File; /** @@ -18,9 +17,9 @@ public class FileCreatedAsyncEvent extends UserEvent { private File file; /** - * Document linked to the file. + * Language of the file. */ - private Document document; + private String language; /** * Unencrypted input stream containing the file. @@ -42,12 +41,12 @@ public class FileCreatedAsyncEvent extends UserEvent { this.file = file; } - public Document getDocument() { - return document; + public String getLanguage() { + return language; } - public void setDocument(Document document) { - this.document = document; + public void setLanguage(String language) { + this.language = language; } public InputStream getInputStream() { @@ -70,7 +69,7 @@ public class FileCreatedAsyncEvent extends UserEvent { public String toString() { return MoreObjects.toStringHelper(this) .add("file", file) - .add("document", document) + .add("language", language) .toString(); } } \ No newline at end of file diff --git a/docs-core/src/main/java/com/sismics/docs/core/event/FileDeletedAsyncEvent.java b/docs-core/src/main/java/com/sismics/docs/core/event/FileDeletedAsyncEvent.java index 96637094..05835ae5 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/event/FileDeletedAsyncEvent.java +++ b/docs-core/src/main/java/com/sismics/docs/core/event/FileDeletedAsyncEvent.java @@ -14,20 +14,10 @@ public class FileDeletedAsyncEvent extends UserEvent { */ private File file; - /** - * Getter of file. - * - * @return the file - */ public File getFile() { return file; } - /** - * Setter of file. - * - * @param file file - */ public void setFile(File file) { this.file = file; } diff --git a/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentDeletedAsyncListener.java b/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentDeletedAsyncListener.java index 1eb04570..acee2ae8 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentDeletedAsyncListener.java +++ b/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentDeletedAsyncListener.java @@ -32,6 +32,6 @@ public class DocumentDeletedAsyncListener { // Update Lucene index LuceneDao luceneDao = new LuceneDao(); - luceneDao.deleteDocument(documentDeletedAsyncEvent.getDocument().getId()); + luceneDao.deleteDocument(documentDeletedAsyncEvent.getDocumentId()); } } diff --git a/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentUpdatedAsyncListener.java b/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentUpdatedAsyncListener.java index 788a3467..5df6b41a 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentUpdatedAsyncListener.java +++ b/docs-core/src/main/java/com/sismics/docs/core/listener/async/DocumentUpdatedAsyncListener.java @@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory; import com.google.common.eventbus.Subscribe; import com.sismics.docs.core.dao.jpa.ContributorDao; +import com.sismics.docs.core.dao.jpa.DocumentDao; import com.sismics.docs.core.dao.lucene.LuceneDao; import com.sismics.docs.core.event.DocumentUpdatedAsyncEvent; import com.sismics.docs.core.model.jpa.Contributor; @@ -35,12 +36,17 @@ public class DocumentUpdatedAsyncListener { log.info("Document updated event: " + event.toString()); } - // Update contributors list TransactionUtil.handle(new Runnable() { @Override public void run() { + // Update Lucene index + DocumentDao documentDao = new DocumentDao(); + LuceneDao luceneDao = new LuceneDao(); + luceneDao.updateDocument(documentDao.getById(event.getDocumentId())); + + // Update contributors list ContributorDao contributorDao = new ContributorDao(); - List contributorList = contributorDao.findByDocumentId(event.getDocument().getId()); + List contributorList = contributorDao.findByDocumentId(event.getDocumentId()); // Check if the user firing this event is not already a contributor for (Contributor contributor : contributorList) { @@ -52,14 +58,10 @@ public class DocumentUpdatedAsyncListener { // Add a new contributor Contributor contributor = new Contributor(); - contributor.setDocumentId(event.getDocument().getId()); + contributor.setDocumentId(event.getDocumentId()); contributor.setUserId(event.getUserId()); contributorDao.create(contributor); } }); - - // Update Lucene index - LuceneDao luceneDao = new LuceneDao(); - luceneDao.updateDocument(event.getDocument()); } } diff --git a/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java b/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java index 0eacdeca..a5301769 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java +++ b/docs-core/src/main/java/com/sismics/docs/core/listener/async/FileCreatedAsyncListener.java @@ -41,7 +41,7 @@ public class FileCreatedAsyncListener { // Extract text content from the file long startTime = System.currentTimeMillis(); - final String content = FileUtil.extractContent(fileCreatedAsyncEvent.getDocument(), file, + final String content = FileUtil.extractContent(fileCreatedAsyncEvent.getLanguage(), file, fileCreatedAsyncEvent.getInputStream(), fileCreatedAsyncEvent.getPdfInputStream()); fileCreatedAsyncEvent.getInputStream().close(); if (fileCreatedAsyncEvent.getPdfInputStream() != null) { @@ -66,6 +66,6 @@ public class FileCreatedAsyncListener { // Update Lucene index LuceneDao luceneDao = new LuceneDao(); - luceneDao.createFile(fileCreatedAsyncEvent.getFile(), fileCreatedAsyncEvent.getDocument()); + luceneDao.createFile(fileCreatedAsyncEvent.getFile()); } } diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java index 64d0552e..2a005fce 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java +++ b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java @@ -18,7 +18,6 @@ import org.imgscalr.Scalr.Mode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.File; import com.sismics.tess4j.Tesseract; import com.sismics.util.ImageUtil; @@ -37,17 +36,17 @@ public class FileUtil { /** * Extract content from a file. * - * @param document Document linked to the file + * @param language Language to extract * @param file File to extract * @param inputStream Unencrypted input stream * @param pdfInputStream Unencrypted PDF input stream * @return Content extract */ - public static String extractContent(Document document, File file, InputStream inputStream, InputStream pdfInputStream) { + public static String extractContent(String language, File file, InputStream inputStream, InputStream pdfInputStream) { String content = null; if (ImageUtil.isImage(file.getMimeType())) { - content = ocrFile(inputStream, document); + content = ocrFile(inputStream, language); } else if (pdfInputStream != null) { content = PdfUtil.extractPdf(pdfInputStream); } @@ -59,10 +58,10 @@ public class FileUtil { * Optical character recognition on a stream. * * @param inputStream Unencrypted input stream - * @param document Document linked to the file + * @param language Language to OCR * @return Content extracted */ - private static String ocrFile(InputStream inputStream, Document document) { + private static String ocrFile(InputStream inputStream, String language) { Tesseract instance = Tesseract.getInstance(); String content = null; BufferedImage image = null; @@ -80,7 +79,7 @@ public class FileUtil { // OCR the file try { log.info("Starting OCR with TESSDATA_PREFIX=" + System.getenv("TESSDATA_PREFIX") + ";LC_NUMERIC=" + System.getenv("LC_NUMERIC")); - instance.setLanguage(document.getLanguage()); + instance.setLanguage(language); content = instance.doOCR(image); } catch (Throwable e) { log.error("Error while OCR-izing the image", e); diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/PdfUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/PdfUtil.java index 7b2043b5..fd9c2678 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/util/PdfUtil.java +++ b/docs-core/src/main/java/com/sismics/docs/core/util/PdfUtil.java @@ -143,24 +143,37 @@ public class PdfUtil { * * @param fileList List of files * @param fitImageToPage Fit images to the page + * @param metadata Add a page with metadata + * @param comment Add a page with comments * @param margin Margins in millimeters * @return PDF input stream * @throws IOException */ - public static InputStream convertToPdf(List fileList, boolean fitImageToPage, int margin) throws Exception { + public static InputStream convertToPdf(List fileList, boolean fitImageToPage, boolean metadata, boolean comments, int margin) throws Exception { // TODO PDF Export: Option to add a front page with: // document title, document description, creator, date created, language, // additional dublincore metadata (except relations) // list of all files (and information if it is in this document or not) // TODO PDF Export: Option to add the comments - - // Create a blank PDF + + // Setup PDFBox Closer closer = Closer.create(); MemoryUsageSetting memUsageSettings = MemoryUsageSetting.setupMixed(1000000); // 1MB max memory usage memUsageSettings.setTempDir(new java.io.File(System.getProperty("java.io.tmpdir"))); // To OS temp float mmPerInch = 1 / (10 * 2.54f) * 72f; + // Create a blank PDF try (PDDocument doc = new PDDocument(memUsageSettings)) { + // Add metadata + if (metadata) { + + } + + // Add comments + if (comments) { + + } + // Add files for (File file : fileList) { Path storedFile = DirectoryUtil.getStorageDirectory().resolve(file.getId()); diff --git a/docs-core/src/test/java/com/sismics/docs/core/util/TestFileUtil.java b/docs-core/src/test/java/com/sismics/docs/core/util/TestFileUtil.java index 7e04aaf2..c768d4cb 100644 --- a/docs-core/src/test/java/com/sismics/docs/core/util/TestFileUtil.java +++ b/docs-core/src/test/java/com/sismics/docs/core/util/TestFileUtil.java @@ -81,7 +81,7 @@ public class TestFileUtil { file4.setId("document_odt"); file4.setMimeType(MimeType.OPEN_DOCUMENT_TEXT); - PdfUtil.convertToPdf(Lists.newArrayList(file0, file1, file2, file3, file4), true, 10).close(); + PdfUtil.convertToPdf(Lists.newArrayList(file0, file1, file2, file3, file4), true, true, true, 10).close(); } } } 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 4c25953e..41313b55 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 @@ -95,16 +95,11 @@ public class DocumentResource extends BaseResource { DocumentDao documentDao = new DocumentDao(); AclDao aclDao = new AclDao(); - DocumentDto documentDto = documentDao.getDocument(documentId); + DocumentDto documentDto = documentDao.getDocument(documentId, PermType.READ, shareId == null ? principal.getId() : shareId); if (documentDto == null) { return Response.status(Status.NOT_FOUND).build(); } - // Check document visibility - if (!aclDao.checkPermission(documentId, PermType.READ, shareId == null ? principal.getId() : shareId)) { - throw new ForbiddenClientException(); - } - JsonObjectBuilder document = Json.createObjectBuilder() .add("id", documentDto.getId()) .add("title", documentDto.getTitle()) @@ -200,8 +195,8 @@ public class DocumentResource extends BaseResource { public Response getPdf( @PathParam("id") String documentId, @QueryParam("share") String shareId, - @QueryParam("metadata") Boolean metadata, - @QueryParam("comments") Boolean comments, + final @QueryParam("metadata") Boolean metadata, + final @QueryParam("comments") Boolean comments, final @QueryParam("fitimagetopage") Boolean fitImageToPage, @QueryParam("margin") String marginStr) { authenticate(); @@ -211,8 +206,8 @@ public class DocumentResource extends BaseResource { // Get document and check read permission DocumentDao documentDao = new DocumentDao(); - Document document = documentDao.getDocument(documentId, PermType.READ, shareId == null ? principal.getId() : shareId); - if (document == null) { + DocumentDto documentDto = documentDao.getDocument(documentId, PermType.READ, shareId == null ? principal.getId() : shareId); + if (documentDto == null) { return Response.status(Status.NOT_FOUND).build(); } @@ -231,7 +226,7 @@ public class DocumentResource extends BaseResource { StreamingOutput stream = new StreamingOutput() { @Override public void write(OutputStream outputStream) throws IOException, WebApplicationException { - try (InputStream inputStream = PdfUtil.convertToPdf(fileList, fitImageToPage, margin)) { + try (InputStream inputStream = PdfUtil.convertToPdf(fileList, fitImageToPage, metadata, comments, margin)) { ByteStreams.copy(inputStream, outputStream); } catch (Exception e) { throw new IOException(e); @@ -243,7 +238,7 @@ public class DocumentResource extends BaseResource { return Response.ok(stream) .header("Content-Type", MimeType.APPLICATION_PDF) - .header("Content-Disposition", "inline; filename=\"" + document.getTitle() + ".pdf\"") + .header("Content-Disposition", "inline; filename=\"" + documentDto.getTitle() + ".pdf\"") .build(); } @@ -568,10 +563,15 @@ public class DocumentResource extends BaseResource { throw new ClientException("ValidationError", MessageFormat.format("{0} is not a supported language", language)); } + // Check write permission + AclDao aclDao = new AclDao(); + if (!aclDao.checkPermission(id, PermType.WRITE, principal.getId())) { + throw new ForbiddenClientException(); + } + // Get the document DocumentDao documentDao = new DocumentDao(); - Document document; - document = documentDao.getDocument(id, PermType.WRITE, principal.getId()); + Document document = documentDao.getById(id); if (document == null) { return Response.status(Status.NOT_FOUND).build(); } @@ -622,10 +622,10 @@ public class DocumentResource extends BaseResource { // Update relations updateRelationList(id, relationList); - // Raise a document updated event + // Raise a document updated event (with the document to update Lucene) DocumentUpdatedAsyncEvent documentUpdatedAsyncEvent = new DocumentUpdatedAsyncEvent(); documentUpdatedAsyncEvent.setUserId(principal.getId()); - documentUpdatedAsyncEvent.setDocument(document); + documentUpdatedAsyncEvent.setDocumentId(id); AppContext.getInstance().getAsyncEventBus().post(documentUpdatedAsyncEvent); JsonObjectBuilder response = Json.createObjectBuilder() @@ -697,14 +697,14 @@ public class DocumentResource extends BaseResource { // Get the document DocumentDao documentDao = new DocumentDao(); FileDao fileDao = new FileDao(); - Document document = documentDao.getDocument(id, PermType.WRITE, principal.getId()); - List fileList = fileDao.getByDocumentId(principal.getId(), id); - if (document == null) { + DocumentDto documentDto = documentDao.getDocument(id, PermType.WRITE, principal.getId()); + if (documentDto == null) { return Response.status(Status.NOT_FOUND).build(); } + List fileList = fileDao.getByDocumentId(principal.getId(), id); // Delete the document - documentDao.delete(document.getId(), principal.getId()); + documentDao.delete(documentDto.getId(), principal.getId()); // Raise file deleted events (don't bother sending document updated event) for (File file : fileList) { @@ -717,7 +717,7 @@ public class DocumentResource extends BaseResource { // Raise a document deleted event DocumentDeletedAsyncEvent documentDeletedAsyncEvent = new DocumentDeletedAsyncEvent(); documentDeletedAsyncEvent.setUserId(principal.getId()); - documentDeletedAsyncEvent.setDocument(document); + documentDeletedAsyncEvent.setDocumentId(documentDto.getId()); AppContext.getInstance().getAsyncEventBus().post(documentDeletedAsyncEvent); // Always return OK 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 4c97756c..b8c4386a 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 @@ -48,7 +48,6 @@ import com.sismics.docs.core.event.DocumentUpdatedAsyncEvent; import com.sismics.docs.core.event.FileCreatedAsyncEvent; import com.sismics.docs.core.event.FileDeletedAsyncEvent; import com.sismics.docs.core.model.context.AppContext; -import com.sismics.docs.core.model.jpa.Document; import com.sismics.docs.core.model.jpa.File; import com.sismics.docs.core.model.jpa.User; import com.sismics.docs.core.util.DirectoryUtil; @@ -94,13 +93,13 @@ public class FileResource extends BaseResource { User user = userDao.getById(principal.getId()); // Get the document - Document document = null; + DocumentDto documentDto = null; if (Strings.isNullOrEmpty(documentId)) { documentId = null; } else { DocumentDao documentDao = new DocumentDao(); - document = documentDao.getDocument(documentId, PermType.WRITE, principal.getId()); - if (document == null) { + documentDto = documentDao.getDocument(documentId, PermType.WRITE, principal.getId()); + if (documentDto == null) { return Response.status(Status.NOT_FOUND).build(); } } @@ -165,7 +164,7 @@ public class FileResource extends BaseResource { if (documentId != null) { FileCreatedAsyncEvent fileCreatedAsyncEvent = new FileCreatedAsyncEvent(); fileCreatedAsyncEvent.setUserId(principal.getId()); - fileCreatedAsyncEvent.setDocument(document); + fileCreatedAsyncEvent.setLanguage(documentDto.getLanguage()); fileCreatedAsyncEvent.setFile(file); fileCreatedAsyncEvent.setInputStream(fileInputStream); fileCreatedAsyncEvent.setPdfInputStream(pdfIntputStream); @@ -173,7 +172,7 @@ public class FileResource extends BaseResource { DocumentUpdatedAsyncEvent documentUpdatedAsyncEvent = new DocumentUpdatedAsyncEvent(); documentUpdatedAsyncEvent.setUserId(principal.getId()); - documentUpdatedAsyncEvent.setDocument(document); + documentUpdatedAsyncEvent.setDocumentId(documentId); AppContext.getInstance().getAsyncEventBus().post(documentUpdatedAsyncEvent); } @@ -214,8 +213,8 @@ public class FileResource extends BaseResource { DocumentDao documentDao = new DocumentDao(); FileDao fileDao = new FileDao(); File file = fileDao.getFile(id, principal.getId()); - Document document = documentDao.getDocument(documentId, PermType.WRITE, principal.getId()); - if (file == null || document == null) { + DocumentDto documentDto = documentDao.getDocument(documentId, PermType.WRITE, principal.getId()); + if (file == null || documentDto == null) { return Response.status(Status.NOT_FOUND).build(); } @@ -236,14 +235,14 @@ public class FileResource extends BaseResource { final InputStream responseInputStream = EncryptionUtil.decryptInputStream(fileInputStream, user.getPrivateKey()); FileCreatedAsyncEvent fileCreatedAsyncEvent = new FileCreatedAsyncEvent(); fileCreatedAsyncEvent.setUserId(principal.getId()); - fileCreatedAsyncEvent.setDocument(document); + fileCreatedAsyncEvent.setLanguage(documentDto.getLanguage()); fileCreatedAsyncEvent.setFile(file); fileCreatedAsyncEvent.setInputStream(responseInputStream); AppContext.getInstance().getAsyncEventBus().post(fileCreatedAsyncEvent); DocumentUpdatedAsyncEvent documentUpdatedAsyncEvent = new DocumentUpdatedAsyncEvent(); documentUpdatedAsyncEvent.setUserId(principal.getId()); - documentUpdatedAsyncEvent.setDocument(document); + documentUpdatedAsyncEvent.setDocumentId(documentId); AppContext.getInstance().getAsyncEventBus().post(documentUpdatedAsyncEvent); } catch (Exception e) { throw new ClientException("AttachError", "Error attaching file to document", e); @@ -364,14 +363,14 @@ public class FileResource extends BaseResource { return Response.status(Status.NOT_FOUND).build(); } - Document document = null; + DocumentDto documentDto = null; if (file.getDocumentId() == null) { // It's an orphan file if (!file.getUserId().equals(principal.getId())) { // But not ours throw new ForbiddenClientException(); } - } else if ((document = documentDao.getDocument(file.getDocumentId(), PermType.WRITE, principal.getId())) == null) { + } else if ((documentDto = documentDao.getDocument(file.getDocumentId(), PermType.WRITE, principal.getId())) == null) { return Response.status(Status.NOT_FOUND).build(); } @@ -395,11 +394,11 @@ public class FileResource extends BaseResource { fileDeletedAsyncEvent.setFile(file); AppContext.getInstance().getAsyncEventBus().post(fileDeletedAsyncEvent); - if (document != null) { + if (documentDto != null) { // Raise a new document updated DocumentUpdatedAsyncEvent documentUpdatedAsyncEvent = new DocumentUpdatedAsyncEvent(); documentUpdatedAsyncEvent.setUserId(principal.getId()); - documentUpdatedAsyncEvent.setDocument(document); + documentUpdatedAsyncEvent.setDocumentId(documentDto.getId()); AppContext.getInstance().getAsyncEventBus().post(documentUpdatedAsyncEvent); } @@ -520,17 +519,11 @@ public class FileResource extends BaseResource { // Get the document DocumentDao documentDao = new DocumentDao(); - DocumentDto documentDto = documentDao.getDocument(documentId); + DocumentDto documentDto = documentDao.getDocument(documentId, PermType.READ, shareId == null ? principal.getId() : shareId); if (documentDto == null) { return Response.status(Status.NOT_FOUND).build(); } - // Check document visibility - AclDao aclDao = new AclDao(); - if (!aclDao.checkPermission(documentId, PermType.READ, shareId == null ? principal.getId() : shareId)) { - throw new ForbiddenClientException(); - } - // Get files and user associated with this document FileDao fileDao = new FileDao(); final UserDao userDao = new UserDao(); diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java index dbc35005..779c2ab1 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/UserResource.java @@ -362,7 +362,7 @@ public class UserResource extends BaseResource { for (Document document : documentList) { DocumentDeletedAsyncEvent documentDeletedAsyncEvent = new DocumentDeletedAsyncEvent(); documentDeletedAsyncEvent.setUserId(principal.getId()); - documentDeletedAsyncEvent.setDocument(document); + documentDeletedAsyncEvent.setDocumentId(document.getId()); AppContext.getInstance().getAsyncEventBus().post(documentDeletedAsyncEvent); } @@ -421,7 +421,7 @@ public class UserResource extends BaseResource { for (Document document : documentList) { DocumentDeletedAsyncEvent documentDeletedAsyncEvent = new DocumentDeletedAsyncEvent(); documentDeletedAsyncEvent.setUserId(principal.getId()); - documentDeletedAsyncEvent.setDocument(document); + documentDeletedAsyncEvent.setDocumentId(document.getId()); AppContext.getInstance().getAsyncEventBus().post(documentDeletedAsyncEvent); } diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java index 3dba5baf..cd423707 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java @@ -57,7 +57,7 @@ public class TestAclResource extends BaseJerseyTest { Response response = target().path("/document/" + document1Id).request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token) .get(); - Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); + Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus())); // Add an ACL READ for acl2 with acl1 json = target().path("/acl").request() @@ -144,7 +144,7 @@ public class TestAclResource extends BaseJerseyTest { response = target().path("/document/" + document1Id).request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token) .get(); - Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus())); + Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus())); // Delete the ACL READ for acl1 with acl1 response = target().path("/acl/" + document1Id + "/READ/" + acl1Id).request() diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java index b90a7f36..5451a3ed 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java @@ -299,7 +299,7 @@ public class TestDocumentResource extends BaseJerseyTest { .cookie(TokenBasedSecurityFilter.COOKIE_NAME, document1Token) .get(JsonObject.class); documents = json.getJsonArray("documents"); - Assert.assertTrue(documents.size() == 1); + Assert.assertEquals(1, documents.size()); // Get document 1 json = target().path("/document/" + document1Id).request()