mirror of
https://github.com/sismics/docs.git
synced 2024-11-25 23:27:57 +01:00
commit
f98a12b96f
@ -90,7 +90,7 @@ public class CommentDao {
|
||||
*/
|
||||
public List<CommentDto> 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;
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
17
docs-core/src/test/java/com/sismics/util/TestImageUtil.java
Normal file
17
docs-core/src/test/java/com/sismics/util/TestImageUtil.java
Normal file
@ -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 "));
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@
|
||||
<org.imgscalr.imgscalr-lib.version>4.2</org.imgscalr.imgscalr-lib.version>
|
||||
<org.apache.pdfbox.pdfbox.version>2.0.0-RC1</org.apache.pdfbox.pdfbox.version>
|
||||
<org.bouncycastle.bcprov-jdk15on.version>1.53</org.bouncycastle.bcprov-jdk15on.version>
|
||||
<joda-time.joda-time.version>2.9</joda-time.joda-time.version>
|
||||
<joda-time.joda-time.version>2.9.1</joda-time.joda-time.version>
|
||||
<org.hibernate.hibernate.version>4.1.0.Final</org.hibernate.hibernate.version>
|
||||
<javax.servlet.javax.servlet-api.version>3.1.0</javax.servlet.javax.servlet-api.version>
|
||||
<com.levigo.jbig2.levigo-jbig2-imageio.version>1.6.3</com.levigo.jbig2.levigo-jbig2-imageio.version>
|
||||
|
@ -158,6 +158,9 @@ public class TokenBasedSecurityFilter implements Filter {
|
||||
Set<String> baseFunctionSet = userBaseFuction.findByRoleId(user.getRoleId());
|
||||
userPrincipal.setBaseFunctionSet(baseFunctionSet);
|
||||
|
||||
// Add email
|
||||
userPrincipal.setEmail(user.getEmail());
|
||||
|
||||
request.setAttribute(PRINCIPAL_ATTRIBUTE, userPrincipal);
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,6 @@
|
||||
</systemProperties>
|
||||
<webApp>
|
||||
<contextPath>/docs-web</contextPath>
|
||||
<overrideDescriptor>src/dev/main/webapp/web-override.xml</overrideDescriptor>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
@ -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">
|
||||
|
||||
<!-- Override init parameter to avoid nasty file locking issue on windows. -->
|
||||
<servlet>
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
|
@ -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">
|
||||
<display-name>Docs</display-name>
|
||||
|
||||
<!-- This filter is used to process a couple things in the request context -->
|
||||
@ -55,4 +56,6 @@
|
||||
<servlet-name>JerseyServlet</servlet-name>
|
||||
<url-pattern>/api/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<absolute-ordering/>
|
||||
</web-app>
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -15,7 +15,8 @@
|
||||
<a ng-href="#/document/view/{{ log.target }}">{{ log.message }}</a>
|
||||
</span>
|
||||
<span ng-switch-when="File">
|
||||
<a ng-href="#/document/view/{{ log.message }}/content/file/{{ log.target }}">Open</a>
|
||||
<a ng-if="log.message" ng-href="#/document/view/{{ log.message }}/content/file/{{ log.target }}">Open</a>
|
||||
<a ng-if="!log.message" ng-href="#/document/file/{{ log.target }}">Open</a>
|
||||
</span>
|
||||
<span ng-switch-when="Comment">
|
||||
<a ng-href="#/document/view/{{ log.message }}">See</a>
|
||||
|
@ -72,15 +72,20 @@
|
||||
<p ng-show="!comments && commentsError">Error loading comments</p>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="comment in comments" style="overflow: hidden">
|
||||
<strong>{{ comment.creator }}</strong>
|
||||
<p>
|
||||
{{ comment.content }}<br />
|
||||
<span class="text-muted">{{ comment.create_date | date: 'yyyy-MM-dd' }}</span>
|
||||
<div ng-repeat="comment in comments" class="media" style="overflow: hidden">
|
||||
<div class="pull-left">
|
||||
<img ng-src="http://www.gravatar.com/avatar/{{ comment.creator_gravatar }}?s=40&d=identicon" class="media-object" />
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<strong>{{ comment.creator }}</strong>
|
||||
<p>
|
||||
{{ comment.content }}<br />
|
||||
<span class="text-muted">{{ comment.create_date | date: 'yyyy-MM-dd' }}</span>
|
||||
<span class="text-muted pull-right btn-link"
|
||||
ng-show="document.writable || userInfo.username == comment.creator"
|
||||
ng-click="deleteComment(comment)">Delete</span>
|
||||
</p>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form ng-submit="addComment()">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="row">
|
||||
<div class="well col-md-12">
|
||||
<div class="col-md-10">
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
{{ document.title }} <small>{{ document.create_date | date: 'yyyy-MM-dd' }}</small>
|
||||
@ -26,4 +26,31 @@
|
||||
|
||||
<div ui-view="file"></div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-2">
|
||||
<p class="page-header">
|
||||
<span class="glyphicon glyphicon-comment"></span>
|
||||
Comments
|
||||
</p>
|
||||
|
||||
<div ng-show="!comments || comments.length == 0" class="text-center text-muted">
|
||||
<h1 class="glyphicon glyphicon-comment"></h1>
|
||||
<p ng-show="!comments && !commentsError">Loading...</p>
|
||||
<p ng-show="comments.length == 0">No comments on this document yet</p>
|
||||
<p ng-show="!comments && commentsError">Error loading comments</p>
|
||||
</div>
|
||||
|
||||
<div ng-repeat="comment in comments" class="media" style="overflow: hidden">
|
||||
<div class="pull-left">
|
||||
<img ng-src="http://www.gravatar.com/avatar/{{ comment.creator_gravatar }}?s=40&d=identicon" class="media-object" />
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<strong>{{ comment.creator }}</strong>
|
||||
<p>
|
||||
{{ comment.content }}<br />
|
||||
<span class="text-muted">{{ comment.create_date | date: 'yyyy-MM-dd' }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app id="docs"
|
||||
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">
|
||||
|
||||
<!-- Override init parameter to avoid nasty file locking issue on windows. -->
|
||||
<servlet>
|
||||
<servlet-name>default</servlet-name>
|
||||
<init-param>
|
||||
<param-name>useFileMappedBuffer</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
</web-app>
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user