mirror of
https://github.com/sismics/docs.git
synced 2024-12-22 19:33:47 +01:00
Closes #68: Add contributors list on documents
This commit is contained in:
parent
2824878065
commit
943465a390
@ -0,0 +1,80 @@
|
||||
package com.sismics.docs.core.dao.jpa;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import com.sismics.docs.core.dao.jpa.dto.ContributorDto;
|
||||
import com.sismics.docs.core.model.jpa.Contributor;
|
||||
import com.sismics.util.context.ThreadLocalContext;
|
||||
|
||||
/**
|
||||
* Contributor DAO.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class ContributorDao {
|
||||
/**
|
||||
* Creates a new contributor.
|
||||
*
|
||||
* @param contributor Contributor
|
||||
* @param userId User ID
|
||||
* @return New ID
|
||||
* @throws Exception
|
||||
*/
|
||||
public String create(Contributor contributor) {
|
||||
// Create the UUID
|
||||
contributor.setId(UUID.randomUUID().toString());
|
||||
|
||||
// Create the contributor
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
em.persist(contributor);
|
||||
|
||||
return contributor.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of all contributors by document.
|
||||
*
|
||||
* @param documentId Document ID
|
||||
* @return List of contributors
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Contributor> findByDocumentId(String documentId) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createQuery("select c from Contributor c where c.documentId = :documentId");
|
||||
q.setParameter("documentId", documentId);
|
||||
return q.getResultList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of all contributors by document.
|
||||
*
|
||||
* @param documentId Document ID
|
||||
* @return List of contributors
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<ContributorDto> getByDocumentId(String documentId) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
StringBuilder sb = new StringBuilder("select u.USE_USERNAME_C, u.USE_EMAIL_C from T_CONTRIBUTOR c ");
|
||||
sb.append(" join T_USER u on u.USE_ID_C = c.CTR_IDUSER_C ");
|
||||
sb.append(" where c.CTR_IDDOC_C = :documentId ");
|
||||
Query q = em.createNativeQuery(sb.toString());
|
||||
q.setParameter("documentId", documentId);
|
||||
List<Object[]> l = q.getResultList();
|
||||
|
||||
// Assemble results
|
||||
List<ContributorDto> contributorDtoList = new ArrayList<>();
|
||||
for (Object[] o : l) {
|
||||
int i = 0;
|
||||
ContributorDto contributorDto = new ContributorDto();
|
||||
contributorDto.setUsername((String) o[i++]);
|
||||
contributorDto.setEmail((String) o[i++]);
|
||||
contributorDtoList.add(contributorDto);
|
||||
}
|
||||
return contributorDtoList;
|
||||
}
|
||||
}
|
@ -136,9 +136,10 @@ public class DocumentDao {
|
||||
*/
|
||||
public Document getDocument(String id, PermType perm, String userId) {
|
||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||
Query q = em.createNativeQuery("select d.* from T_DOCUMENT d "
|
||||
+ " 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 "
|
||||
+ " where d.DOC_ID_C = :id and d.DOC_DELETEDATE_D is null", Document.class);
|
||||
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);
|
||||
@ -276,7 +277,7 @@ public class DocumentDao {
|
||||
List<Object[]> l = PaginatedLists.executePaginatedQuery(paginatedList, queryParam, sortCriteria);
|
||||
|
||||
// Assemble results
|
||||
List<DocumentDto> documentDtoList = new ArrayList<DocumentDto>();
|
||||
List<DocumentDto> documentDtoList = new ArrayList<>();
|
||||
for (Object[] o : l) {
|
||||
int i = 0;
|
||||
DocumentDto documentDto = new DocumentDto();
|
||||
|
@ -0,0 +1,34 @@
|
||||
package com.sismics.docs.core.dao.jpa.dto;
|
||||
|
||||
/**
|
||||
* Contributor DTO.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
public class ContributorDto {
|
||||
/**
|
||||
* Username.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* Email.
|
||||
*/
|
||||
private String email;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
}
|
@ -4,8 +4,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.sismics.docs.core.dao.jpa.ContributorDao;
|
||||
import com.sismics.docs.core.dao.lucene.LuceneDao;
|
||||
import com.sismics.docs.core.event.DocumentCreatedAsyncEvent;
|
||||
import com.sismics.docs.core.model.jpa.Contributor;
|
||||
import com.sismics.docs.core.util.TransactionUtil;
|
||||
|
||||
/**
|
||||
* Listener on document created.
|
||||
@ -21,17 +24,29 @@ public class DocumentCreatedAsyncListener {
|
||||
/**
|
||||
* Document created.
|
||||
*
|
||||
* @param documentCreatedAsyncEvent Document created event
|
||||
* @param event Document created event
|
||||
* @throws Exception
|
||||
*/
|
||||
@Subscribe
|
||||
public void on(final DocumentCreatedAsyncEvent documentCreatedAsyncEvent) throws Exception {
|
||||
public void on(final DocumentCreatedAsyncEvent event) throws Exception {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Document created event: " + documentCreatedAsyncEvent.toString());
|
||||
log.info("Document created event: " + event.toString());
|
||||
}
|
||||
|
||||
TransactionUtil.handle(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Add the first contributor (the creator of the document)
|
||||
ContributorDao contributorDao = new ContributorDao();
|
||||
Contributor contributor = new Contributor();
|
||||
contributor.setDocumentId(event.getDocument().getId());
|
||||
contributor.setUserId(event.getUserId());
|
||||
contributorDao.create(contributor);
|
||||
}
|
||||
});
|
||||
|
||||
// Update Lucene index
|
||||
LuceneDao luceneDao = new LuceneDao();
|
||||
luceneDao.createDocument(documentCreatedAsyncEvent.getDocument());
|
||||
luceneDao.createDocument(event.getDocument());
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,16 @@
|
||||
package com.sismics.docs.core.listener.async;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.sismics.docs.core.dao.jpa.ContributorDao;
|
||||
import com.sismics.docs.core.dao.lucene.LuceneDao;
|
||||
import com.sismics.docs.core.event.DocumentUpdatedAsyncEvent;
|
||||
import com.sismics.docs.core.model.jpa.Contributor;
|
||||
import com.sismics.docs.core.util.TransactionUtil;
|
||||
|
||||
/**
|
||||
* Listener on document updated.
|
||||
@ -21,17 +26,40 @@ public class DocumentUpdatedAsyncListener {
|
||||
/**
|
||||
* Document updated.
|
||||
*
|
||||
* @param documentUpdatedAsyncEvent Document updated event
|
||||
* @param event Document updated event
|
||||
* @throws Exception
|
||||
*/
|
||||
@Subscribe
|
||||
public void on(final DocumentUpdatedAsyncEvent documentUpdatedAsyncEvent) throws Exception {
|
||||
public void on(final DocumentUpdatedAsyncEvent event) throws Exception {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Document updated event: " + documentUpdatedAsyncEvent.toString());
|
||||
log.info("Document updated event: " + event.toString());
|
||||
}
|
||||
|
||||
// Update contributors list
|
||||
TransactionUtil.handle(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ContributorDao contributorDao = new ContributorDao();
|
||||
List<Contributor> contributorList = contributorDao.findByDocumentId(event.getDocument().getId());
|
||||
|
||||
// Check if the user firing this event is not already a contributor
|
||||
for (Contributor contributor : contributorList) {
|
||||
if (contributor.getUserId().equals(event.getUserId())) {
|
||||
// The current user is already a contributor on this document, don't do anything
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new contributor
|
||||
Contributor contributor = new Contributor();
|
||||
contributor.setDocumentId(event.getDocument().getId());
|
||||
contributor.setUserId(event.getUserId());
|
||||
contributorDao.create(contributor);
|
||||
}
|
||||
});
|
||||
|
||||
// Update Lucene index
|
||||
LuceneDao luceneDao = new LuceneDao();
|
||||
luceneDao.updateDocument(documentUpdatedAsyncEvent.getDocument());
|
||||
luceneDao.updateDocument(event.getDocument());
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
package com.sismics.docs.core.model.jpa;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
/**
|
||||
* Contributor entity.
|
||||
*
|
||||
* @author bgamard
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "T_Contributor")
|
||||
public class Contributor {
|
||||
/**
|
||||
* Contributor ID.
|
||||
*/
|
||||
@Id
|
||||
@Column(name = "CTR_ID_C", length = 36)
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Document ID.
|
||||
*/
|
||||
@Column(name = "CTR_IDDOC_C", length = 36, nullable = false)
|
||||
private String documentId;
|
||||
|
||||
/**
|
||||
* User ID.
|
||||
*/
|
||||
@Column(name = "CTR_IDUSER_C", length = 36, nullable = false)
|
||||
private String userId;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDocumentId() {
|
||||
return documentId;
|
||||
}
|
||||
|
||||
public void setDocumentId(String documentId) {
|
||||
this.documentId = documentId;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this)
|
||||
.add("id", id)
|
||||
.add("userId", userId)
|
||||
.add("documentId", documentId)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ alter table T_DOCUMENT add column DOC_RIGHTS_C varchar(500);
|
||||
alter table T_AUDIT_LOG add column LOG_IDUSER_C varchar(36) not null default 'admin';
|
||||
|
||||
create memory table T_VOCABULARY ( VOC_ID_C varchar(36) not null, VOC_NAME_C varchar(50) not null, VOC_VALUE_C varchar(500) not null, VOC_ORDER_N int not null, primary key (VOC_ID_C) );
|
||||
create cached table T_CONTRIBUTOR ( CTR_ID_C varchar(36) not null, CTR_IDUSER_C varchar(36) not null, CTR_IDDOC_C varchar(36) not null, primary key (CTR_ID_C) );
|
||||
|
||||
insert into T_VOCABULARY(VOC_ID_C, VOC_NAME_C, VOC_VALUE_C, VOC_ORDER_N) values('type-collection', 'type', 'Collection', 0);
|
||||
insert into T_VOCABULARY(VOC_ID_C, VOC_NAME_C, VOC_VALUE_C, VOC_ORDER_N) values('type-dataset', 'type', 'Dataset', 1);
|
||||
|
@ -40,12 +40,14 @@ import com.google.common.io.ByteStreams;
|
||||
import com.sismics.docs.core.constant.Constants;
|
||||
import com.sismics.docs.core.constant.PermType;
|
||||
import com.sismics.docs.core.dao.jpa.AclDao;
|
||||
import com.sismics.docs.core.dao.jpa.ContributorDao;
|
||||
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
||||
import com.sismics.docs.core.dao.jpa.FileDao;
|
||||
import com.sismics.docs.core.dao.jpa.TagDao;
|
||||
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||
import com.sismics.docs.core.dao.jpa.criteria.DocumentCriteria;
|
||||
import com.sismics.docs.core.dao.jpa.dto.AclDto;
|
||||
import com.sismics.docs.core.dao.jpa.dto.ContributorDto;
|
||||
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
||||
import com.sismics.docs.core.dao.jpa.dto.TagDto;
|
||||
import com.sismics.docs.core.event.DocumentCreatedAsyncEvent;
|
||||
@ -159,6 +161,17 @@ public class DocumentResource extends BaseResource {
|
||||
document.add("acls", aclList)
|
||||
.add("writable", writable);
|
||||
|
||||
// Add contributors
|
||||
ContributorDao contributorDao = new ContributorDao();
|
||||
List<ContributorDto> contributorDtoList = contributorDao.getByDocumentId(documentId);
|
||||
JsonArrayBuilder contributorList = Json.createArrayBuilder();
|
||||
for (ContributorDto contributorDto : contributorDtoList) {
|
||||
contributorList.add(Json.createObjectBuilder()
|
||||
.add("username", contributorDto.getUsername())
|
||||
.add("email", contributorDto.getEmail()));
|
||||
}
|
||||
document.add("contributors", contributorList);
|
||||
|
||||
return Response.ok().entity(document.build()).build();
|
||||
}
|
||||
|
||||
|
@ -100,20 +100,36 @@ public class TestAclResource extends BaseJerseyTest {
|
||||
acls = json.getJsonArray("acls");
|
||||
Assert.assertEquals(4, acls.size());
|
||||
|
||||
// Update the document as acl2
|
||||
json = target().path("/document/" + document1Id).request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||
.post(Entity.form(new Form()
|
||||
.param("title", "My new super document 1")), JsonObject.class);
|
||||
Assert.assertEquals(document1Id, json.getString("id"));
|
||||
|
||||
// Get the document as acl2
|
||||
json = target().path("/document/" + document1Id).request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||
.get(JsonObject.class);
|
||||
Assert.assertEquals(document1Id, json.getString("id"));
|
||||
JsonArray contributors = json.getJsonArray("contributors");
|
||||
Assert.assertEquals(2, contributors.size());
|
||||
|
||||
// Delete the ACL WRITE for acl2 with acl2
|
||||
target().path("/acl/" + document1Id + "/WRITE/" + acl2Id).request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||
.delete();
|
||||
.delete(JsonObject.class);
|
||||
|
||||
// Delete the ACL READ for acl2 with acl2
|
||||
target().path("/acl/" + document1Id + "/READ/" + acl2Id).request()
|
||||
// Delete the ACL READ for acl2 with acl2 (not authorized)
|
||||
response = target().path("/acl/" + document1Id + "/READ/" + acl2Id).request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl2Token)
|
||||
.delete();
|
||||
Assert.assertEquals(Status.FORBIDDEN, Status.fromStatusCode(response.getStatus()));
|
||||
|
||||
// Delete the ACL READ for acl2 with acl1
|
||||
target().path("/acl/" + document1Id + "/READ/" + acl2Id).request()
|
||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, acl1Token)
|
||||
.delete();
|
||||
.delete(JsonObject.class);
|
||||
|
||||
// Get the document as acl1
|
||||
json = target().path("/document/" + document1Id).request()
|
||||
|
@ -222,6 +222,9 @@ public class TestDocumentResource extends BaseJerseyTest {
|
||||
tags = json.getJsonArray("tags");
|
||||
Assert.assertEquals(1, tags.size());
|
||||
Assert.assertEquals(tag1Id, tags.getJsonObject(0).getString("id"));
|
||||
JsonArray contributors = json.getJsonArray("contributors");
|
||||
Assert.assertEquals(1, contributors.size());
|
||||
Assert.assertEquals("document1", contributors.getJsonObject(0).getString("username"));
|
||||
|
||||
// Export a document in PDF format
|
||||
Response response = target().path("/document/" + document1Id).request()
|
||||
@ -279,6 +282,9 @@ public class TestDocumentResource extends BaseJerseyTest {
|
||||
tags = json.getJsonArray("tags");
|
||||
Assert.assertEquals(1, tags.size());
|
||||
Assert.assertEquals(tag2Id, tags.getJsonObject(0).getString("id"));
|
||||
contributors = json.getJsonArray("contributors");
|
||||
Assert.assertEquals(1, contributors.size());
|
||||
Assert.assertEquals("document1", contributors.getJsonObject(0).getString("username"));
|
||||
|
||||
// Deletes a document
|
||||
json = target().path("/document/" + document1Id).request()
|
||||
|
Loading…
Reference in New Issue
Block a user