diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/CommentDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/CommentDao.java index c7108661..23ad1b46 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/CommentDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/CommentDao.java @@ -90,7 +90,7 @@ public class CommentDao { */ public List getByDocumentId(String documentId) { EntityManager em = ThreadLocalContext.get().getEntityManager(); - StringBuilder sb = new StringBuilder("select c.COM_ID_C, c.COM_CONTENT_C, c.COM_CREATEDATE_D, u.USE_USERNAME_C from T_COMMENT c, T_USER u"); + StringBuilder sb = new StringBuilder("select c.COM_ID_C, c.COM_CONTENT_C, c.COM_CREATEDATE_D, u.USE_USERNAME_C, u.USE_EMAIL_C from T_COMMENT c, T_USER u"); sb.append(" where c.COM_IDDOC_C = :documentId and c.COM_IDUSER_C = u.USE_ID_C and c.COM_DELETEDATE_D is null "); sb.append(" order by c.COM_CREATEDATE_D asc "); Query q = em.createNativeQuery(sb.toString()); @@ -106,6 +106,7 @@ public class CommentDao { commentDto.setContent((String) o[i++]); commentDto.setCreateTimestamp(((Timestamp) o[i++]).getTime()); commentDto.setCreatorName((String) o[i++]); + commentDto.setCreatorEmail((String) o[i++]); commentDtoList.add(commentDto); } return commentDtoList; 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 6c47b2b2..49a70b4c 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 @@ -224,7 +224,7 @@ public class DocumentDao { if (criteria.getTagIdList() != null && !criteria.getTagIdList().isEmpty()) { int index = 0; for (String tagId : criteria.getTagIdList()) { - sb.append(" join T_DOCUMENT_TAG dt" + index + " on dt" + index + ".DOT_IDDOCUMENT_C = d.DOC_ID_C and dt" + index + ".DOT_IDTAG_C = :tagId" + index + " "); + sb.append(" join T_DOCUMENT_TAG dt" + index + " on dt" + index + ".DOT_IDDOCUMENT_C = d.DOC_ID_C and dt" + index + ".DOT_IDTAG_C = :tagId" + index + " and dt" + index + ".DOT_DELETEDATE_D is null "); parameterMap.put("tagId" + index, tagId); index++; } diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/CommentDto.java b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/CommentDto.java index 446fad8e..1f2e6d41 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/CommentDto.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/jpa/dto/CommentDto.java @@ -19,6 +19,11 @@ public class CommentDto { */ private String creatorName; + /** + * Creator email. + */ + private String creatorEmail; + /** * Content. */ @@ -44,6 +49,14 @@ public class CommentDto { public void setCreatorName(String creatorName) { this.creatorName = creatorName; } + + public String getCreatorEmail() { + return creatorEmail; + } + + public void setCreatorEmail(String creatorEmail) { + this.creatorEmail = creatorEmail; + } public String getContent() { return content; diff --git a/docs-core/src/main/java/com/sismics/util/ImageUtil.java b/docs-core/src/main/java/com/sismics/util/ImageUtil.java index 001ba76b..40e163fd 100644 --- a/docs-core/src/main/java/com/sismics/util/ImageUtil.java +++ b/docs-core/src/main/java/com/sismics/util/ImageUtil.java @@ -11,6 +11,8 @@ import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; +import com.google.common.base.Charsets; +import com.google.common.hash.Hashing; import com.sismics.util.mime.MimeType; /** @@ -62,4 +64,21 @@ public class ImageUtil { public static boolean isImage(String mimeType) { return mimeType.equals(MimeType.IMAGE_GIF) || mimeType.equals(MimeType.IMAGE_PNG) || mimeType.equals(MimeType.IMAGE_JPEG); } + + /** + * Compute Gravatar hash. + * See https://en.gravatar.com/site/implement/hash/. + * + * @param email + * @return Gravatar hash + */ + public static String computeGravatar(String email) { + if (email == null) { + return null; + } + + return Hashing.md5().hashString( + email.trim().toLowerCase(), Charsets.UTF_8) + .toString(); + } } diff --git a/docs-core/src/test/java/com/sismics/util/TestImageUtil.java b/docs-core/src/test/java/com/sismics/util/TestImageUtil.java new file mode 100644 index 00000000..d6c62703 --- /dev/null +++ b/docs-core/src/test/java/com/sismics/util/TestImageUtil.java @@ -0,0 +1,17 @@ +package com.sismics.util; + +import junit.framework.Assert; +import org.junit.Test; + +/** + * Test of the image utilities. + * + * @author bgamard + */ +public class TestImageUtil { + + @Test + public void computeGravatarTest() throws Exception { + Assert.assertEquals("0bc83cb571cd1c50ba6f3e8a78ef1346", ImageUtil.computeGravatar("MyEmailAddress@example.com ")); + } +} diff --git a/docs-parent/pom.xml b/docs-parent/pom.xml index 895168e5..8015a475 100644 --- a/docs-parent/pom.xml +++ b/docs-parent/pom.xml @@ -32,7 +32,7 @@ 4.2 2.0.0-RC1 1.53 - 2.9 + 2.9.1 4.1.0.Final 3.1.0 1.6.3 diff --git a/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java b/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java index 037cc94c..2e65cc9a 100644 --- a/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java +++ b/docs-web-common/src/main/java/com/sismics/util/filter/TokenBasedSecurityFilter.java @@ -158,6 +158,9 @@ public class TokenBasedSecurityFilter implements Filter { Set baseFunctionSet = userBaseFuction.findByRoleId(user.getRoleId()); userPrincipal.setBaseFunctionSet(baseFunctionSet); + // Add email + userPrincipal.setEmail(user.getEmail()); + request.setAttribute(PRINCIPAL_ATTRIBUTE, userPrincipal); } diff --git a/docs-web/pom.xml b/docs-web/pom.xml index 5fee5f2a..29016e40 100644 --- a/docs-web/pom.xml +++ b/docs-web/pom.xml @@ -219,7 +219,6 @@ /docs-web - src/dev/main/webapp/web-override.xml diff --git a/docs-web/src/dev/main/webapp/web-override.xml b/docs-web/src/dev/main/webapp/web-override.xml index ea56b8c9..1dea0dae 100644 --- a/docs-web/src/dev/main/webapp/web-override.xml +++ b/docs-web/src/dev/main/webapp/web-override.xml @@ -3,7 +3,8 @@ xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" - version="3.0"> + version="3.0" + metadata-complete="true"> diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/CommentResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/CommentResource.java index 54d393af..a940e989 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/CommentResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/CommentResource.java @@ -11,6 +11,7 @@ import javax.ws.rs.GET; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -21,6 +22,7 @@ import com.sismics.docs.core.dao.jpa.dto.CommentDto; import com.sismics.docs.core.model.jpa.Comment; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.util.ValidationUtil; +import com.sismics.util.ImageUtil; /** * Comment REST resource. @@ -64,8 +66,9 @@ public class CommentResource extends BaseResource { // Returns the comment JsonObjectBuilder response = Json.createObjectBuilder() .add("id", comment.getId()) - .add("creator", principal.getName()) .add("content", comment.getContent()) + .add("creator", principal.getName()) + .add("creator_gravatar", ImageUtil.computeGravatar(principal.getEmail())) .add("create_date", comment.getCreateDate().getTime()); return Response.ok().entity(response.build()).build(); } @@ -119,14 +122,13 @@ public class CommentResource extends BaseResource { */ @GET @Path("{documentId: [a-z0-9\\-]+}") - public Response get(@PathParam("documentId") String documentId) { - if (!authenticate()) { - throw new ForbiddenClientException(); - } + public Response get(@PathParam("documentId") String documentId, + @QueryParam("share") String shareId) { + authenticate(); // Read access on doc gives access to read comments DocumentDao documentDao = new DocumentDao(); - if (documentDao.getDocument(documentId, PermType.READ, principal.getId()) == null) { + if (documentDao.getDocument(documentId, PermType.READ, shareId == null ? principal.getId() : shareId) == null) { return Response.status(Status.NOT_FOUND).build(); } @@ -139,6 +141,7 @@ public class CommentResource extends BaseResource { .add("id", commentDto.getId()) .add("content", commentDto.getContent()) .add("creator", commentDto.getCreatorName()) + .add("creator_gravatar", ImageUtil.computeGravatar(commentDto.getCreatorEmail())) .add("create_date", commentDto.getCreateTimestamp())); } diff --git a/docs-web/src/main/webapp/WEB-INF/web.xml b/docs-web/src/main/webapp/WEB-INF/web.xml index de15dab3..0c5629fb 100644 --- a/docs-web/src/main/webapp/WEB-INF/web.xml +++ b/docs-web/src/main/webapp/WEB-INF/web.xml @@ -3,7 +3,8 @@ xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" - version="3.0"> + version="3.0" + metadata-complete="true"> Docs @@ -55,4 +56,6 @@ JerseyServlet /api/* + + diff --git a/docs-web/src/main/webapp/src/app/share/controller/Share.js b/docs-web/src/main/webapp/src/app/share/controller/Share.js index c1e15ae6..c85f65c8 100644 --- a/docs-web/src/main/webapp/src/app/share/controller/Share.js +++ b/docs-web/src/main/webapp/src/app/share/controller/Share.js @@ -20,6 +20,13 @@ angular.module('share').controller('Share', function($scope, $state, $stateParam $scope.files = data.files; }); + // Load comments from server + Restangular.one('comment', $stateParams.documentId).get({ share: $stateParams.shareId }).then(function(data) { + $scope.comments = data.comments; + }, function(response) { + $scope.commentsError = response; + }); + /** * Navigate to the selected file. */ diff --git a/docs-web/src/main/webapp/src/partial/docs/directive.auditlog.html b/docs-web/src/main/webapp/src/partial/docs/directive.auditlog.html index 1986122f..483bf18b 100644 --- a/docs-web/src/main/webapp/src/partial/docs/directive.auditlog.html +++ b/docs-web/src/main/webapp/src/partial/docs/directive.auditlog.html @@ -15,7 +15,8 @@ {{ log.message }} - Open + Open + Open See diff --git a/docs-web/src/main/webapp/src/partial/docs/document.view.html b/docs-web/src/main/webapp/src/partial/docs/document.view.html index 5ad747e5..f3f4ad86 100644 --- a/docs-web/src/main/webapp/src/partial/docs/document.view.html +++ b/docs-web/src/main/webapp/src/partial/docs/document.view.html @@ -72,15 +72,20 @@

Error loading comments

-
- {{ comment.creator }} -

- {{ comment.content }}
- {{ comment.create_date | date: 'yyyy-MM-dd' }} +

+
+ +
+
+ {{ comment.creator }} +

+ {{ comment.content }}
+ {{ comment.create_date | date: 'yyyy-MM-dd' }} Delete -

+

+
diff --git a/docs-web/src/main/webapp/src/partial/share/share.html b/docs-web/src/main/webapp/src/partial/share/share.html index 42efc1b1..25833a68 100644 --- a/docs-web/src/main/webapp/src/partial/share/share.html +++ b/docs-web/src/main/webapp/src/partial/share/share.html @@ -1,5 +1,5 @@
-
+
+ +
+ + +
+

+

Loading...

+

No comments on this document yet

+

Error loading comments

+
+ +
+
+ +
+
+ {{ comment.creator }} +

+ {{ comment.content }}
+ {{ comment.create_date | date: 'yyyy-MM-dd' }} +

+
+
+
\ No newline at end of file diff --git a/docs-web/src/stress/main/webapp/web-override.xml b/docs-web/src/stress/main/webapp/web-override.xml deleted file mode 100644 index ea56b8c9..00000000 --- a/docs-web/src/stress/main/webapp/web-override.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - default - - useFileMappedBuffer - false - - - diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestCommentResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestCommentResource.java index 798414ee..b59551dd 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestCommentResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestCommentResource.java @@ -127,6 +127,7 @@ public class TestCommentResource extends BaseJerseyTest { Assert.assertEquals(comment2Id, comment.getString("id")); Assert.assertEquals("Comment by comment2", comment.getString("content")); Assert.assertEquals("comment2", comment.getString("creator")); + Assert.assertEquals("d6e56c42f61983bba80d370138763420", comment.getString("creator_gravatar")); Assert.assertNotNull(comment.getJsonNumber("create_date")); // Delete a comment with comment2 diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestShareResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestShareResource.java index ba641334..eea8ab85 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestShareResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestShareResource.java @@ -78,6 +78,14 @@ public class TestShareResource extends BaseJerseyTest { Assert.assertEquals(document1Id, json.getString("id")); Assert.assertEquals(3, json.getJsonArray("acls").size()); // 2 for the creator, 1 for the share + // Get all comments from this document anonymously + json = target().path("/comment/" + document1Id) + .queryParam("share", share1Id) + .request() + .get(JsonObject.class); + JsonArray comments = json.getJsonArray("comments"); + Assert.assertEquals(0, comments.size()); + // Get all files from this document anonymously json = target().path("/file/list") .queryParam("id", document1Id)