mirror of
https://github.com/sismics/docs.git
synced 2025-01-10 20:25:11 +01:00
commit
bee8a4fcdc
@ -25,7 +25,7 @@ Features
|
|||||||
- Flexible search engine
|
- Flexible search engine
|
||||||
- Full text search in image and PDF
|
- Full text search in image and PDF
|
||||||
- 256-bit AES encryption
|
- 256-bit AES encryption
|
||||||
- Tag system
|
- Tag system with relations
|
||||||
- Multi-users ACL system
|
- Multi-users ACL system
|
||||||
- Audit log
|
- Audit log
|
||||||
- Document sharing by URL
|
- Document sharing by URL
|
||||||
|
@ -114,9 +114,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
TagListAdapter adapter = (TagListAdapter) tagListView.getAdapter();
|
TagListAdapter adapter = (TagListAdapter) tagListView.getAdapter();
|
||||||
if (adapter == null) return;
|
if (adapter == null) return;
|
||||||
JSONObject tag = adapter.getItem(position);
|
TagListAdapter.TagItem tagItem = adapter.getItem(position);
|
||||||
if (tag == null) return;
|
if (tagItem == null) return;
|
||||||
searchQuery("tag:" + tag.optString("name"));
|
searchQuery("tag:" + tagItem.getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package com.sismics.docs.adapter;
|
package com.sismics.docs.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -17,8 +19,6 @@ import org.json.JSONArray;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,7 +30,7 @@ public class TagListAdapter extends BaseAdapter {
|
|||||||
/**
|
/**
|
||||||
* Tags.
|
* Tags.
|
||||||
*/
|
*/
|
||||||
private List<JSONObject> tags;
|
private List<TagItem> tagItemList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag list adapter.
|
* Tag list adapter.
|
||||||
@ -38,33 +38,53 @@ public class TagListAdapter extends BaseAdapter {
|
|||||||
* @param tagsArray Tags
|
* @param tagsArray Tags
|
||||||
*/
|
*/
|
||||||
public TagListAdapter(JSONArray tagsArray) {
|
public TagListAdapter(JSONArray tagsArray) {
|
||||||
this.tags = new ArrayList<>();
|
List<JSONObject> tags = new ArrayList<>();
|
||||||
for (int i = 0; i < tagsArray.length(); i++) {
|
for (int i = 0; i < tagsArray.length(); i++) {
|
||||||
tags.add(tagsArray.optJSONObject(i));
|
tags.add(tagsArray.optJSONObject(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort tags by count desc
|
// Reorder tags by parent/child relation and compute depth
|
||||||
Collections.sort(tags, new Comparator<JSONObject>() {
|
int depth = 0;
|
||||||
@Override
|
initTags(tags, JSONObject.NULL.toString(), depth);
|
||||||
public int compare(JSONObject lhs, JSONObject rhs) {
|
}
|
||||||
return lhs.optInt("count") < rhs.optInt("count") ? 1 : -1;
|
|
||||||
|
/**
|
||||||
|
* Init tags model recursively.
|
||||||
|
*
|
||||||
|
* @param tags All tags from server
|
||||||
|
* @param parentId Parent ID
|
||||||
|
* @param depth Depth
|
||||||
|
*/
|
||||||
|
private void initTags(List<JSONObject> tags, String parentId, int depth) {
|
||||||
|
// Get all tags with this parent
|
||||||
|
for (JSONObject tag : tags) {
|
||||||
|
String tagParentId = tag.optString("parent");
|
||||||
|
if (tagParentId.equals(parentId)) {
|
||||||
|
TagItem tagItem = new TagItem();
|
||||||
|
tagItem.id = tag.optString("id");
|
||||||
|
tagItem.name = tag.optString("name");
|
||||||
|
tagItem.count = tag.optInt("count");
|
||||||
|
tagItem.color = tag.optString("color");
|
||||||
|
tagItem.depth = depth;
|
||||||
|
tagItemList.add(tagItem);
|
||||||
|
initTags(tags, tagItem.id, depth + 1);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return tags.size();
|
return tagItemList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject getItem(int position) {
|
public TagItem getItem(int position) {
|
||||||
return tags.get(position);
|
return tagItemList.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
return getItem(position).optString("id").hashCode();
|
return getItem(position).id.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,19 +95,41 @@ public class TagListAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill the view
|
// Fill the view
|
||||||
JSONObject tag = getItem(position);
|
TagItem tagItem = getItem(position);
|
||||||
TextView tagTextView = (TextView) view.findViewById(R.id.tagTextView);
|
TextView tagTextView = (TextView) view.findViewById(R.id.tagTextView);
|
||||||
tagTextView.setText(tag.optString("name"));
|
tagTextView.setText(tagItem.name);
|
||||||
TextView tagCountTextView = (TextView) view.findViewById(R.id.tagCountTextView);
|
TextView tagCountTextView = (TextView) view.findViewById(R.id.tagCountTextView);
|
||||||
tagCountTextView.setText(tag.optString("count"));
|
tagCountTextView.setText(String.format("%d", tagItem.count));
|
||||||
|
|
||||||
// Label color filtering
|
// Label color filtering
|
||||||
ImageView labelImageView = (ImageView) view.findViewById(R.id.labelImageView);
|
ImageView labelImageView = (ImageView) view.findViewById(R.id.labelImageView);
|
||||||
Drawable labelDrawable = labelImageView.getDrawable().mutate();
|
Drawable labelDrawable = labelImageView.getDrawable().mutate();
|
||||||
labelDrawable.setColorFilter(Color.parseColor(tag.optString("color")), PorterDuff.Mode.MULTIPLY);
|
labelDrawable.setColorFilter(Color.parseColor(tagItem.color), PorterDuff.Mode.MULTIPLY);
|
||||||
labelImageView.setImageDrawable(labelDrawable);
|
labelImageView.setImageDrawable(labelDrawable);
|
||||||
labelImageView.invalidate();
|
labelImageView.invalidate();
|
||||||
|
|
||||||
|
// Offset according to depth
|
||||||
|
Resources resources = parent.getContext().getResources();
|
||||||
|
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) labelImageView.getLayoutParams();
|
||||||
|
layoutParams.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tagItem.depth * 12, resources.getDisplayMetrics());
|
||||||
|
labelImageView.setLayoutParams(layoutParams);
|
||||||
|
labelImageView.requestLayout();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tag item in the tags list.
|
||||||
|
*/
|
||||||
|
public static class TagItem {
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private int count;
|
||||||
|
private String color;
|
||||||
|
private int depth;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,7 @@ public class AuditLogDao {
|
|||||||
// ACL on document is not checked here, it's assumed
|
// ACL on document is not checked here, it's assumed
|
||||||
queries.add(baseQuery + " where l.LOG_IDENTITY_C = :documentId ");
|
queries.add(baseQuery + " where l.LOG_IDENTITY_C = :documentId ");
|
||||||
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select f.FIL_ID_C from T_FILE f where f.FIL_IDDOC_C = :documentId) ");
|
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select f.FIL_ID_C from T_FILE f where f.FIL_IDDOC_C = :documentId) ");
|
||||||
|
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select c.COM_ID_C from T_COMMENT c where c.COM_IDDOC_C = :documentId) ");
|
||||||
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select a.ACL_ID_C from T_ACL a where a.ACL_SOURCEID_C = :documentId) ");
|
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select a.ACL_ID_C from T_ACL a where a.ACL_SOURCEID_C = :documentId) ");
|
||||||
parameterMap.put("documentId", criteria.getDocumentId());
|
parameterMap.put("documentId", criteria.getDocumentId());
|
||||||
}
|
}
|
||||||
@ -76,6 +77,7 @@ public class AuditLogDao {
|
|||||||
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select t.TAG_ID_C from T_TAG t where t.TAG_IDUSER_C = :userId) ");
|
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select t.TAG_ID_C from T_TAG t where t.TAG_IDUSER_C = :userId) ");
|
||||||
// Show only logs from owned documents, ACL are lost on delete
|
// Show only logs from owned documents, ACL are lost on delete
|
||||||
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select d.DOC_ID_C from T_DOCUMENT d where d.DOC_IDUSER_C = :userId) ");
|
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select d.DOC_ID_C from T_DOCUMENT d where d.DOC_IDUSER_C = :userId) ");
|
||||||
|
queries.add(baseQuery + " where l.LOG_IDENTITY_C in (select c.COM_ID_C from T_COMMENT c where c.COM_IDUSER_C = :userId) ");
|
||||||
parameterMap.put("userId", criteria.getUserId());
|
parameterMap.put("userId", criteria.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,113 @@
|
|||||||
|
package com.sismics.docs.core.dao.jpa;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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.constant.AuditLogType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.CommentDto;
|
||||||
|
import com.sismics.docs.core.model.jpa.Comment;
|
||||||
|
import com.sismics.docs.core.util.AuditLogUtil;
|
||||||
|
import com.sismics.util.context.ThreadLocalContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment DAO.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class CommentDao {
|
||||||
|
/**
|
||||||
|
* Creates a new comment.
|
||||||
|
*
|
||||||
|
* @param comment Comment
|
||||||
|
* @return New ID
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public String create(Comment comment) {
|
||||||
|
// Create the UUID
|
||||||
|
comment.setId(UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
// Create the comment
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
comment.setCreateDate(new Date());
|
||||||
|
em.persist(comment);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(comment, AuditLogType.CREATE);
|
||||||
|
|
||||||
|
return comment.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a comment.
|
||||||
|
*
|
||||||
|
* @param id Comment ID
|
||||||
|
*/
|
||||||
|
public void delete(String id) {
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
|
||||||
|
// Get the document
|
||||||
|
Query q = em.createQuery("select c from Comment c where c.id = :id and c.deleteDate is null");
|
||||||
|
q.setParameter("id", id);
|
||||||
|
Comment commentDb = (Comment) q.getSingleResult();
|
||||||
|
|
||||||
|
// Delete the document
|
||||||
|
Date dateNow = new Date();
|
||||||
|
commentDb.setDeleteDate(dateNow);
|
||||||
|
|
||||||
|
// Create audit log
|
||||||
|
AuditLogUtil.create(commentDb, AuditLogType.DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an active comment by its ID.
|
||||||
|
*
|
||||||
|
* @param id Comment ID
|
||||||
|
* @return Comment
|
||||||
|
*/
|
||||||
|
public Comment getActiveById(String id) {
|
||||||
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
|
try {
|
||||||
|
Query q = em.createQuery("select c from Comment c where c.id = :id and c.deleteDate is null");
|
||||||
|
q.setParameter("id", id);
|
||||||
|
return (Comment) q.getSingleResult();
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all comments on a document.
|
||||||
|
*
|
||||||
|
* @param documentId Document ID
|
||||||
|
* @return List of comments
|
||||||
|
*/
|
||||||
|
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");
|
||||||
|
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());
|
||||||
|
q.setParameter("documentId", documentId);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Object[]> l = q.getResultList();
|
||||||
|
|
||||||
|
List<CommentDto> commentDtoList = new ArrayList<CommentDto>();
|
||||||
|
for (Object[] o : l) {
|
||||||
|
int i = 0;
|
||||||
|
CommentDto commentDto = new CommentDto();
|
||||||
|
commentDto.setId((String) o[i++]);
|
||||||
|
commentDto.setContent((String) o[i++]);
|
||||||
|
commentDto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
|
||||||
|
commentDto.setCreatorName((String) o[i++]);
|
||||||
|
commentDtoList.add(commentDto);
|
||||||
|
}
|
||||||
|
return commentDtoList;
|
||||||
|
}
|
||||||
|
}
|
@ -83,7 +83,12 @@ public class DocumentDao {
|
|||||||
sb.append(" where d.DOC_IDUSER_C = u.USE_ID_C and d.DOC_ID_C = :id and d.DOC_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());
|
Query q = em.createNativeQuery(sb.toString());
|
||||||
q.setParameter("id", id);
|
q.setParameter("id", id);
|
||||||
Object[] o = (Object[]) q.getSingleResult();
|
Object[] o = null;
|
||||||
|
try {
|
||||||
|
o = (Object[]) q.getSingleResult();
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
DocumentDto documentDto = new DocumentDto();
|
DocumentDto documentDto = new DocumentDto();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -114,7 +119,11 @@ public class DocumentDao {
|
|||||||
q.setParameter("id", id);
|
q.setParameter("id", id);
|
||||||
q.setParameter("perm", perm.name());
|
q.setParameter("perm", perm.name());
|
||||||
q.setParameter("userId", userId);
|
q.setParameter("userId", userId);
|
||||||
return (Document) q.getSingleResult();
|
try {
|
||||||
|
return (Document) q.getSingleResult();
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,11 @@ public class FileDao {
|
|||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
Query q = em.createQuery("select f from File f where f.id = :id and f.deleteDate is null");
|
Query q = em.createQuery("select f from File f where f.id = :id and f.deleteDate is null");
|
||||||
q.setParameter("id", id);
|
q.setParameter("id", id);
|
||||||
return (File) q.getSingleResult();
|
try {
|
||||||
|
return (File) q.getSingleResult();
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,7 +82,11 @@ public class FileDao {
|
|||||||
Query q = em.createQuery("select f from File f where f.id = :id and f.userId = :userId and f.deleteDate is null");
|
Query q = em.createQuery("select f from File f where f.id = :id and f.userId = :userId and f.deleteDate is null");
|
||||||
q.setParameter("id", id);
|
q.setParameter("id", id);
|
||||||
q.setParameter("userId", userId);
|
q.setParameter("userId", userId);
|
||||||
return (File) q.getSingleResult();
|
try {
|
||||||
|
return (File) q.getSingleResult();
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.sismics.docs.core.dao.jpa.dto;
|
||||||
|
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment DTO.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class CommentDto {
|
||||||
|
/**
|
||||||
|
* Comment ID.
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creator name.
|
||||||
|
*/
|
||||||
|
private String creatorName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content.
|
||||||
|
*/
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creation date of this comment.
|
||||||
|
*/
|
||||||
|
private Long createTimestamp;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreatorName() {
|
||||||
|
return creatorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatorName(String creatorName) {
|
||||||
|
this.creatorName = creatorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCreateTimestamp() {
|
||||||
|
return createTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateTimestamp(Long createTimestamp) {
|
||||||
|
this.createTimestamp = createTimestamp;
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,6 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EntityListeners;
|
|
||||||
import javax.persistence.EnumType;
|
import javax.persistence.EnumType;
|
||||||
import javax.persistence.Enumerated;
|
import javax.persistence.Enumerated;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
@ -12,7 +11,6 @@ import javax.persistence.Table;
|
|||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.sismics.docs.core.constant.PermType;
|
import com.sismics.docs.core.constant.PermType;
|
||||||
import com.sismics.docs.core.util.AuditLogUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ACL entity.
|
* ACL entity.
|
||||||
@ -20,7 +18,6 @@ import com.sismics.docs.core.util.AuditLogUtil;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@EntityListeners(AuditLogUtil.class)
|
|
||||||
@Table(name = "T_ACL")
|
@Table(name = "T_ACL")
|
||||||
public class Acl implements Loggable {
|
public class Acl implements Loggable {
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,179 @@
|
|||||||
|
package com.sismics.docs.core.model.jpa;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment entity.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "T_COMMENT")
|
||||||
|
public class Comment implements Loggable {
|
||||||
|
/**
|
||||||
|
* Comment ID.
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
@Column(name = "COM_ID_C", length = 36)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Document ID.
|
||||||
|
*/
|
||||||
|
@Column(name = "COM_IDDOC_C", length = 36, nullable = false)
|
||||||
|
private String documentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User ID.
|
||||||
|
*/
|
||||||
|
@Column(name = "COM_IDUSER_C", length = 36, nullable = false)
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content.
|
||||||
|
*/
|
||||||
|
@Column(name = "COM_CONTENT_C", nullable = false)
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creation date.
|
||||||
|
*/
|
||||||
|
@Column(name = "COM_CREATEDATE_D", nullable = false)
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletion date.
|
||||||
|
*/
|
||||||
|
@Column(name = "COM_DELETEDATE_D")
|
||||||
|
private Date deleteDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of id.
|
||||||
|
*
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of id.
|
||||||
|
*
|
||||||
|
* @param id id
|
||||||
|
*/
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of documentId.
|
||||||
|
*
|
||||||
|
* @return the documentId
|
||||||
|
*/
|
||||||
|
public String getDocumentId() {
|
||||||
|
return documentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of documentId.
|
||||||
|
*
|
||||||
|
* @param documentId documentId
|
||||||
|
*/
|
||||||
|
public void setDocumentId(String documentId) {
|
||||||
|
this.documentId = documentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of createDate.
|
||||||
|
*
|
||||||
|
* @return the createDate
|
||||||
|
*/
|
||||||
|
public Date getCreateDate() {
|
||||||
|
return createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of createDate.
|
||||||
|
*
|
||||||
|
* @param createDate createDate
|
||||||
|
*/
|
||||||
|
public void setCreateDate(Date createDate) {
|
||||||
|
this.createDate = createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of deleteDate.
|
||||||
|
*
|
||||||
|
* @return the deleteDate
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Date getDeleteDate() {
|
||||||
|
return deleteDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of deleteDate.
|
||||||
|
*
|
||||||
|
* @param deleteDate deleteDate
|
||||||
|
*/
|
||||||
|
public void setDeleteDate(Date deleteDate) {
|
||||||
|
this.deleteDate = deleteDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of content.
|
||||||
|
*
|
||||||
|
* @return the content
|
||||||
|
*/
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of content.
|
||||||
|
*
|
||||||
|
* @param content content
|
||||||
|
*/
|
||||||
|
public void setContent(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of userId.
|
||||||
|
*
|
||||||
|
* @return the userId
|
||||||
|
*/
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of userId.
|
||||||
|
*
|
||||||
|
* @param userId userId
|
||||||
|
*/
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return MoreObjects.toStringHelper(this)
|
||||||
|
.add("id", id)
|
||||||
|
.add("documentId", documentId)
|
||||||
|
.add("userId", userId)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toMessage() {
|
||||||
|
return documentId;
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,10 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EntityListeners;
|
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.sismics.docs.core.util.AuditLogUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document entity.
|
* Document entity.
|
||||||
@ -17,7 +15,6 @@ import com.sismics.docs.core.util.AuditLogUtil;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@EntityListeners(AuditLogUtil.class)
|
|
||||||
@Table(name = "T_DOCUMENT")
|
@Table(name = "T_DOCUMENT")
|
||||||
public class Document implements Loggable {
|
public class Document implements Loggable {
|
||||||
/**
|
/**
|
||||||
|
@ -4,13 +4,11 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EntityListeners;
|
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Lob;
|
import javax.persistence.Lob;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.sismics.docs.core.util.AuditLogUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File entity.
|
* File entity.
|
||||||
@ -18,7 +16,6 @@ import com.sismics.docs.core.util.AuditLogUtil;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@EntityListeners(AuditLogUtil.class)
|
|
||||||
@Table(name = "T_FILE")
|
@Table(name = "T_FILE")
|
||||||
public class File implements Loggable {
|
public class File implements Loggable {
|
||||||
/**
|
/**
|
||||||
|
@ -4,12 +4,10 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EntityListeners;
|
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.sismics.docs.core.util.AuditLogUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag.
|
* Tag.
|
||||||
@ -17,7 +15,6 @@ import com.sismics.docs.core.util.AuditLogUtil;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@EntityListeners(AuditLogUtil.class)
|
|
||||||
@Table(name = "T_TAG")
|
@Table(name = "T_TAG")
|
||||||
public class Tag implements Loggable {
|
public class Tag implements Loggable {
|
||||||
/**
|
/**
|
||||||
|
@ -4,12 +4,10 @@ import java.util.Date;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EntityListeners;
|
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.sismics.docs.core.util.AuditLogUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User entity.
|
* User entity.
|
||||||
@ -17,7 +15,6 @@ import com.sismics.docs.core.util.AuditLogUtil;
|
|||||||
* @author jtremeaux
|
* @author jtremeaux
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
@EntityListeners(AuditLogUtil.class)
|
|
||||||
@Table(name = "T_USER")
|
@Table(name = "T_USER")
|
||||||
public class User implements Loggable {
|
public class User implements Loggable {
|
||||||
/**
|
/**
|
||||||
|
@ -5,17 +5,5 @@
|
|||||||
version="2.0">
|
version="2.0">
|
||||||
<persistence-unit name="transactions-optional" transaction-type="RESOURCE_LOCAL">
|
<persistence-unit name="transactions-optional" transaction-type="RESOURCE_LOCAL">
|
||||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||||
|
|
||||||
<class>com.sismics.docs.core.model.jpa.AuthenticationToken</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.BaseFunction</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.Config</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.User</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.RoleBaseFunction</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.Document</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.Tag</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.DocumentTag</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.Share</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.Acl</class>
|
|
||||||
<class>com.sismics.docs.core.model.jpa.AuditLog</class>
|
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
@ -1 +1 @@
|
|||||||
db.version=2
|
db.version=3
|
@ -0,0 +1,4 @@
|
|||||||
|
create cached table T_COMMENT ( COM_ID_C varchar(36) not null, COM_IDDOC_C varchar(36) not null, COM_IDUSER_C varchar(36) not null, COM_CONTENT_C varchar(4000) not null, COM_CREATEDATE_D datetime, COM_DELETEDATE_D datetime, primary key (COM_ID_C) );
|
||||||
|
alter table T_COMMENT add constraint FK_COM_IDDOC_C foreign key (COM_IDDOC_C) references T_DOCUMENT (DOC_ID_C) on delete restrict on update restrict;
|
||||||
|
alter table T_COMMENT add constraint FK_COM_IDUSER_C foreign key (COM_IDUSER_C) references T_USER (USE_ID_C) on delete restrict on update restrict;
|
||||||
|
update T_CONFIG set CFG_VALUE_C = '3' where CFG_ID_C = 'DB_VERSION';
|
@ -25,14 +25,14 @@
|
|||||||
<org.slf4j.version>1.6.4</org.slf4j.version>
|
<org.slf4j.version>1.6.4</org.slf4j.version>
|
||||||
<org.slf4j.jcl-over-slf4j.version>1.6.6</org.slf4j.jcl-over-slf4j.version>
|
<org.slf4j.jcl-over-slf4j.version>1.6.6</org.slf4j.jcl-over-slf4j.version>
|
||||||
<junit.junit.version>4.7</junit.junit.version>
|
<junit.junit.version>4.7</junit.junit.version>
|
||||||
<com.h2database.h2.version>1.4.188</com.h2database.h2.version>
|
<com.h2database.h2.version>1.4.190</com.h2database.h2.version>
|
||||||
<org.glassfish.jersey.version>2.21</org.glassfish.jersey.version>
|
<org.glassfish.jersey.version>2.22.1</org.glassfish.jersey.version>
|
||||||
<org.mindrot.jbcrypt>0.3m</org.mindrot.jbcrypt>
|
<org.mindrot.jbcrypt>0.3m</org.mindrot.jbcrypt>
|
||||||
<org.apache.lucene.version>4.2.0</org.apache.lucene.version>
|
<org.apache.lucene.version>4.2.0</org.apache.lucene.version>
|
||||||
<org.imgscalr.imgscalr-lib.version>4.2</org.imgscalr.imgscalr-lib.version>
|
<org.imgscalr.imgscalr-lib.version>4.2</org.imgscalr.imgscalr-lib.version>
|
||||||
<org.apache.pdfbox.pdfbox.version>2.0.0-SNAPSHOT</org.apache.pdfbox.pdfbox.version>
|
<org.apache.pdfbox.pdfbox.version>2.0.0-RC1</org.apache.pdfbox.pdfbox.version>
|
||||||
<org.bouncycastle.bcprov-jdk15on.version>1.49</org.bouncycastle.bcprov-jdk15on.version>
|
<org.bouncycastle.bcprov-jdk15on.version>1.53</org.bouncycastle.bcprov-jdk15on.version>
|
||||||
<joda-time.joda-time.version>2.8.2</joda-time.joda-time.version>
|
<joda-time.joda-time.version>2.9</joda-time.joda-time.version>
|
||||||
<org.hibernate.hibernate.version>4.1.0.Final</org.hibernate.hibernate.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>
|
<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>
|
<com.levigo.jbig2.levigo-jbig2-imageio.version>1.6.3</com.levigo.jbig2.levigo-jbig2-imageio.version>
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
api.current_version=${project.version}
|
api.current_version=${project.version}
|
||||||
api.min_version=1.0
|
api.min_version=1.0
|
||||||
db.version=2
|
db.version=3
|
@ -0,0 +1,150 @@
|
|||||||
|
package com.sismics.docs.rest.resource;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonArrayBuilder;
|
||||||
|
import javax.json.JsonObjectBuilder;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.FormParam;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import com.sismics.docs.core.constant.PermType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.CommentDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment REST resource.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
@Path("/comment")
|
||||||
|
public class CommentResource extends BaseResource {
|
||||||
|
/**
|
||||||
|
* Add a comment.
|
||||||
|
*
|
||||||
|
* @param documentId Document ID
|
||||||
|
* @param content Comment content
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
public Response add(@FormParam("id") String documentId,
|
||||||
|
@FormParam("content") String content) {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate input data
|
||||||
|
ValidationUtil.validateRequired(documentId, "id");
|
||||||
|
content = ValidationUtil.validateLength(content, "content", 1, 4000, false);
|
||||||
|
|
||||||
|
// Read access on doc gives access to write comments
|
||||||
|
DocumentDao documentDao = new DocumentDao();
|
||||||
|
if (documentDao.getDocument(documentId, PermType.READ, principal.getId()) == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the comment
|
||||||
|
Comment comment = new Comment();
|
||||||
|
comment.setDocumentId(documentId);
|
||||||
|
comment.setContent(content);
|
||||||
|
comment.setUserId(principal.getId());
|
||||||
|
CommentDao commentDao = new CommentDao();
|
||||||
|
commentDao.create(comment);
|
||||||
|
|
||||||
|
// Returns the comment
|
||||||
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
|
.add("id", comment.getId())
|
||||||
|
.add("creator", principal.getName())
|
||||||
|
.add("content", comment.getContent())
|
||||||
|
.add("create_date", comment.getCreateDate().getTime());
|
||||||
|
return Response.ok().entity(response.build()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a comment.
|
||||||
|
*
|
||||||
|
* @param id Comment ID
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
@Path("{id: [a-z0-9\\-]+}")
|
||||||
|
public Response delete(@PathParam("id") String id) {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate input data
|
||||||
|
ValidationUtil.validateRequired(id, "id");
|
||||||
|
|
||||||
|
// Get the comment
|
||||||
|
CommentDao commentDao = new CommentDao();
|
||||||
|
Comment comment = commentDao.getActiveById(id);
|
||||||
|
if (comment == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the current user owns the comment, skip ACL check
|
||||||
|
if (!comment.getUserId().equals(principal.getId())) {
|
||||||
|
// Get the associated document
|
||||||
|
DocumentDao documentDao = new DocumentDao();
|
||||||
|
if (documentDao.getDocument(comment.getDocumentId(), PermType.WRITE, principal.getId()) == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the comment
|
||||||
|
commentDao.delete(id);
|
||||||
|
|
||||||
|
// Always return OK
|
||||||
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
|
.add("status", "ok");
|
||||||
|
return Response.ok().entity(response.build()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all comments on a document.
|
||||||
|
*
|
||||||
|
* @param documentId DocumentID
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("{documentId: [a-z0-9\\-]+}")
|
||||||
|
public Response get(@PathParam("documentId") String documentId) {
|
||||||
|
if (!authenticate()) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read access on doc gives access to read comments
|
||||||
|
DocumentDao documentDao = new DocumentDao();
|
||||||
|
if (documentDao.getDocument(documentId, PermType.READ, principal.getId()) == null) {
|
||||||
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble results
|
||||||
|
CommentDao commentDao = new CommentDao();
|
||||||
|
List<CommentDto> commentDtoList = commentDao.getByDocumentId(documentId);
|
||||||
|
JsonArrayBuilder comments = Json.createArrayBuilder();
|
||||||
|
for (CommentDto commentDto : commentDtoList) {
|
||||||
|
comments.add(Json.createObjectBuilder()
|
||||||
|
.add("id", commentDto.getId())
|
||||||
|
.add("content", commentDto.getContent())
|
||||||
|
.add("creator", commentDto.getCreatorName())
|
||||||
|
.add("create_date", commentDto.getCreateTimestamp()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always return OK
|
||||||
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
|
.add("comments", comments);
|
||||||
|
return Response.ok().entity(response.build()).build();
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,6 @@ import java.util.UUID;
|
|||||||
import javax.json.Json;
|
import javax.json.Json;
|
||||||
import javax.json.JsonArrayBuilder;
|
import javax.json.JsonArrayBuilder;
|
||||||
import javax.json.JsonObjectBuilder;
|
import javax.json.JsonObjectBuilder;
|
||||||
import javax.persistence.NoResultException;
|
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@ -82,17 +81,15 @@ public class DocumentResource extends BaseResource {
|
|||||||
|
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
AclDao aclDao = new AclDao();
|
AclDao aclDao = new AclDao();
|
||||||
DocumentDto documentDto;
|
DocumentDto documentDto = documentDao.getDocument(documentId);
|
||||||
try {
|
if (documentDto == null) {
|
||||||
documentDto = documentDao.getDocument(documentId);
|
|
||||||
|
|
||||||
// Check document visibility
|
|
||||||
if (!aclDao.checkPermission(documentId, PermType.READ, shareId == null ? principal.getId() : shareId)) {
|
|
||||||
throw new ForbiddenClientException();
|
|
||||||
}
|
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
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()
|
JsonObjectBuilder document = Json.createObjectBuilder()
|
||||||
.add("id", documentDto.getId())
|
.add("id", documentDto.getId())
|
||||||
@ -415,9 +412,8 @@ public class DocumentResource extends BaseResource {
|
|||||||
// Get the document
|
// Get the document
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
Document document;
|
Document document;
|
||||||
try {
|
document = documentDao.getDocument(id, PermType.WRITE, principal.getId());
|
||||||
document = documentDao.getDocument(id, PermType.WRITE, principal.getId());
|
if (document == null) {
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,12 +488,9 @@ public class DocumentResource extends BaseResource {
|
|||||||
// Get the document
|
// Get the document
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
FileDao fileDao = new FileDao();
|
FileDao fileDao = new FileDao();
|
||||||
Document document;
|
Document document = documentDao.getDocument(id, PermType.WRITE, principal.getId());
|
||||||
List<File> fileList;
|
List<File> fileList = fileDao.getByDocumentId(principal.getId(), id);
|
||||||
try {
|
if (document == null) {
|
||||||
document = documentDao.getDocument(id, PermType.WRITE, principal.getId());
|
|
||||||
fileList = fileDao.getByDocumentId(principal.getId(), id);
|
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ import java.util.zip.ZipOutputStream;
|
|||||||
import javax.json.Json;
|
import javax.json.Json;
|
||||||
import javax.json.JsonArrayBuilder;
|
import javax.json.JsonArrayBuilder;
|
||||||
import javax.json.JsonObjectBuilder;
|
import javax.json.JsonObjectBuilder;
|
||||||
import javax.persistence.NoResultException;
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
@ -98,9 +97,8 @@ public class FileResource extends BaseResource {
|
|||||||
documentId = null;
|
documentId = null;
|
||||||
} else {
|
} else {
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
try {
|
document = documentDao.getDocument(documentId, PermType.WRITE, principal.getId());
|
||||||
document = documentDao.getDocument(documentId, PermType.WRITE, principal.getId());
|
if (document == null) {
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,12 +188,9 @@ public class FileResource extends BaseResource {
|
|||||||
// Get the document and the file
|
// Get the document and the file
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
FileDao fileDao = new FileDao();
|
FileDao fileDao = new FileDao();
|
||||||
Document document;
|
File file = fileDao.getFile(id, principal.getId());
|
||||||
File file;
|
Document document = documentDao.getDocument(documentId, PermType.WRITE, principal.getId());
|
||||||
try {
|
if (file == null || document == null) {
|
||||||
file = fileDao.getFile(id, principal.getId());
|
|
||||||
document = documentDao.getDocument(documentId, PermType.WRITE, principal.getId());
|
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,9 +246,7 @@ public class FileResource extends BaseResource {
|
|||||||
|
|
||||||
// Get the document
|
// Get the document
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
try {
|
if (documentDao.getDocument(documentId, PermType.WRITE, principal.getId()) == null) {
|
||||||
documentDao.getDocument(documentId, PermType.WRITE, principal.getId());
|
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,19 +323,18 @@ public class FileResource extends BaseResource {
|
|||||||
// Get the file
|
// Get the file
|
||||||
FileDao fileDao = new FileDao();
|
FileDao fileDao = new FileDao();
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
File file;
|
File file = fileDao.getFile(id);
|
||||||
try {
|
if (file == null) {
|
||||||
file = fileDao.getFile(id);
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
if (file.getDocumentId() == null) {
|
}
|
||||||
// It's an orphan file
|
|
||||||
if (!file.getUserId().equals(principal.getId())) {
|
if (file.getDocumentId() == null) {
|
||||||
// But not ours
|
// It's an orphan file
|
||||||
throw new ForbiddenClientException();
|
if (!file.getUserId().equals(principal.getId())) {
|
||||||
}
|
// But not ours
|
||||||
} else {
|
throw new ForbiddenClientException();
|
||||||
documentDao.getDocument(file.getDocumentId(), PermType.WRITE, principal.getId());
|
|
||||||
}
|
}
|
||||||
} catch (NoResultException e) {
|
} else if (documentDao.getDocument(file.getDocumentId(), PermType.WRITE, principal.getId()) == null) {
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,26 +375,24 @@ public class FileResource extends BaseResource {
|
|||||||
// Get the file
|
// Get the file
|
||||||
FileDao fileDao = new FileDao();
|
FileDao fileDao = new FileDao();
|
||||||
UserDao userDao = new UserDao();
|
UserDao userDao = new UserDao();
|
||||||
File file;
|
File file = fileDao.getFile(fileId);
|
||||||
try {
|
if (file == null) {
|
||||||
file = fileDao.getFile(fileId);
|
|
||||||
|
|
||||||
if (file.getDocumentId() == null) {
|
|
||||||
// It's an orphan file
|
|
||||||
if (!file.getUserId().equals(principal.getId())) {
|
|
||||||
// But not ours
|
|
||||||
throw new ForbiddenClientException();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Check document accessibility
|
|
||||||
AclDao aclDao = new AclDao();
|
|
||||||
if (!aclDao.checkPermission(file.getDocumentId(), PermType.READ, shareId == null ? principal.getId() : shareId)) {
|
|
||||||
throw new ForbiddenClientException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file.getDocumentId() == null) {
|
||||||
|
// It's an orphan file
|
||||||
|
if (!file.getUserId().equals(principal.getId())) {
|
||||||
|
// But not ours
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check document accessibility
|
||||||
|
AclDao aclDao = new AclDao();
|
||||||
|
if (!aclDao.checkPermission(file.getDocumentId(), PermType.READ, shareId == null ? principal.getId() : shareId)) {
|
||||||
|
throw new ForbiddenClientException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get the stored file
|
// Get the stored file
|
||||||
@ -470,19 +460,17 @@ public class FileResource extends BaseResource {
|
|||||||
|
|
||||||
// Get the document
|
// Get the document
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
DocumentDto documentDto;
|
DocumentDto documentDto = documentDao.getDocument(documentId);
|
||||||
try {
|
if (documentDto == null) {
|
||||||
documentDto = documentDao.getDocument(documentId);
|
|
||||||
|
|
||||||
// Check document visibility
|
|
||||||
AclDao aclDao = new AclDao();
|
|
||||||
if (!aclDao.checkPermission(documentId, PermType.READ, shareId == null ? principal.getId() : shareId)) {
|
|
||||||
throw new ForbiddenClientException();
|
|
||||||
}
|
|
||||||
} catch (NoResultException e) {
|
|
||||||
return Response.status(Status.NOT_FOUND).build();
|
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
|
// Get files and user associated with this document
|
||||||
FileDao fileDao = new FileDao();
|
FileDao fileDao = new FileDao();
|
||||||
final UserDao userDao = new UserDao();
|
final UserDao userDao = new UserDao();
|
||||||
|
@ -6,13 +6,13 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.json.Json;
|
import javax.json.Json;
|
||||||
import javax.json.JsonObjectBuilder;
|
import javax.json.JsonObjectBuilder;
|
||||||
import javax.persistence.NoResultException;
|
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
import com.sismics.docs.core.constant.AclTargetType;
|
import com.sismics.docs.core.constant.AclTargetType;
|
||||||
import com.sismics.docs.core.constant.PermType;
|
import com.sismics.docs.core.constant.PermType;
|
||||||
@ -53,10 +53,8 @@ public class ShareResource extends BaseResource {
|
|||||||
|
|
||||||
// Get the document
|
// Get the document
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
try {
|
if (documentDao.getDocument(documentId, PermType.WRITE, principal.getId()) == null) {
|
||||||
documentDao.getDocument(documentId, PermType.WRITE, principal.getId());
|
return Response.status(Status.NOT_FOUND).build();
|
||||||
} catch (NoResultException e) {
|
|
||||||
throw new ClientException("DocumentNotFound", MessageFormat.format("Document not found: {0}", documentId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the share
|
// Create the share
|
||||||
|
@ -173,6 +173,14 @@ angular.module('docs',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.state('document.view.content.file', {
|
||||||
|
url: '/file/:fileId',
|
||||||
|
views: {
|
||||||
|
'file': {
|
||||||
|
controller: 'FileView'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
.state('document.view.permissions', {
|
.state('document.view.permissions', {
|
||||||
url: '/permissions',
|
url: '/permissions',
|
||||||
views: {
|
views: {
|
||||||
@ -191,14 +199,6 @@ angular.module('docs',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('document.view.file', {
|
|
||||||
url: '/file/:fileId',
|
|
||||||
views: {
|
|
||||||
'file': {
|
|
||||||
controller: 'FileView'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.state('login', {
|
.state('login', {
|
||||||
url: '/login',
|
url: '/login',
|
||||||
views: {
|
views: {
|
||||||
|
@ -11,6 +11,40 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta
|
|||||||
$scope.error = response;
|
$scope.error = response;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Load comments from server
|
||||||
|
Restangular.one('comment', $stateParams.id).get().then(function(data) {
|
||||||
|
$scope.comments = data.comments;
|
||||||
|
}, function(response) {
|
||||||
|
$scope.commentsError = response;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a comment.
|
||||||
|
*/
|
||||||
|
$scope.comment = '';
|
||||||
|
$scope.addComment = function() {
|
||||||
|
if ($scope.comment.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Restangular.one('comment').put({
|
||||||
|
id: $stateParams.id,
|
||||||
|
content: $scope.comment
|
||||||
|
}).then(function(data) {
|
||||||
|
$scope.comment = '';
|
||||||
|
$scope.comments.push(data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a comment.
|
||||||
|
*/
|
||||||
|
$scope.deleteComment = function(comment) {
|
||||||
|
Restangular.one('comment', comment.id).remove().then(function() {
|
||||||
|
$scope.comments.splice($scope.comments.indexOf(comment), 1);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a document.
|
* Delete a document.
|
||||||
*/
|
*/
|
||||||
@ -24,7 +58,7 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta
|
|||||||
|
|
||||||
$dialog.messageBox(title, msg, btns, function (result) {
|
$dialog.messageBox(title, msg, btns, function (result) {
|
||||||
if (result == 'ok') {
|
if (result == 'ok') {
|
||||||
Restangular.one('document', document.id).remove().then(function () {
|
Restangular.one('document', document.id).remove().then(function() {
|
||||||
$scope.loadDocuments();
|
$scope.loadDocuments();
|
||||||
$state.go('document.default');
|
$state.go('document.default');
|
||||||
});
|
});
|
||||||
|
@ -38,7 +38,7 @@ angular.module('docs').controller('DocumentViewContent', function ($scope, $stat
|
|||||||
* Navigate to the selected file.
|
* Navigate to the selected file.
|
||||||
*/
|
*/
|
||||||
$scope.openFile = function (file) {
|
$scope.openFile = function (file) {
|
||||||
$state.go('document.view.file', { id: $stateParams.id, fileId: file.id })
|
$state.go('document.view.content.file', { id: $stateParams.id, fileId: file.id })
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
<a ng-href="#/document/view/{{ log.target }}">{{ log.message }}</a>
|
<a ng-href="#/document/view/{{ log.target }}">{{ log.message }}</a>
|
||||||
</span>
|
</span>
|
||||||
<span ng-switch-when="File">
|
<span ng-switch-when="File">
|
||||||
<a ng-href="#/document/view/{{ log.message }}/file/{{ log.target }}">Open</a>
|
<a ng-href="#/document/view/{{ log.message }}/content/file/{{ log.target }}">Open</a>
|
||||||
|
</span>
|
||||||
|
<span ng-switch-when="Comment">
|
||||||
|
<a ng-href="#/document/view/{{ log.message }}">See</a>
|
||||||
</span>
|
</span>
|
||||||
<span ng-switch-when="Acl">
|
<span ng-switch-when="Acl">
|
||||||
{{ log.message }}
|
{{ log.message }}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<p ng-bind-html="document.description | newline"></p>
|
<p class="well-sm" ng-bind-html="document.description | newline"></p>
|
||||||
|
|
||||||
<div ng-file-drop drag-over-class="bg-success" ng-multiple="true" allow-dir="false" ng-model="dropFiles"
|
<div ng-file-drop drag-over-class="bg-success" ng-multiple="true" allow-dir="false" ng-model="dropFiles"
|
||||||
accept="image/*,application/pdf,application/zip" ng-file-change="fileDropped($files, $event, $rejectedFiles)">
|
accept="image/*,application/pdf,application/zip" ng-file-change="fileDropped($files, $event, $rejectedFiles)">
|
||||||
<div class="row upload-zone" ui-sortable="fileSortableOptions" ng-model="files">
|
<div class="row upload-zone" ui-sortable="fileSortableOptions" ng-model="files">
|
||||||
<div class="col-xs-6 col-sm-4 col-md-3 col-lg-2 text-center" ng-repeat="file in files">
|
<div class="col-xs-6 col-sm-4 col-md-4 col-lg-3 text-center" ng-repeat="file in files">
|
||||||
<div class="thumbnail" ng-if="file.id">
|
<div class="thumbnail" ng-if="file.id">
|
||||||
<a ng-click="openFile(file)">
|
<a ng-click="openFile(file)">
|
||||||
<img class="thumbnail-file" ng-src="../api/file/{{ file.id }}/data?size=thumb" tooltip="{{ file.mimetype }}" tooltip-placement="top" />
|
<img class="thumbnail-file" ng-src="../api/file/{{ file.id }}/data?size=thumb" tooltip="{{ file.mimetype }}" tooltip-placement="top" />
|
||||||
@ -34,4 +34,6 @@
|
|||||||
Drag & drop files here to upload
|
Drag & drop files here to upload
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div ui-view="file"></div>
|
@ -38,24 +38,57 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="nav nav-tabs">
|
<div class="row">
|
||||||
<li ng-class="{ active: $state.current.name == 'document.view.content' }">
|
<div class="col-md-9">
|
||||||
<a href="#/document/view/{{ document.id }}/content">
|
<ul class="nav nav-tabs">
|
||||||
<span class="glyphicon glyphicon-file"></span> Content
|
<li ng-class="{ active: $state.current.name == 'document.view.content' }">
|
||||||
</a>
|
<a href="#/document/view/{{ document.id }}/content">
|
||||||
</li>
|
<span class="glyphicon glyphicon-file"></span> Content
|
||||||
<li ng-class="{ active: $state.current.name == 'document.view.permissions' }">
|
</a>
|
||||||
<a href="#/document/view/{{ document.id }}/permissions">
|
</li>
|
||||||
<span class="glyphicon glyphicon-user"></span> Permissions
|
<li ng-class="{ active: $state.current.name == 'document.view.permissions' }">
|
||||||
</a>
|
<a href="#/document/view/{{ document.id }}/permissions">
|
||||||
</li>
|
<span class="glyphicon glyphicon-user"></span> Permissions
|
||||||
<li ng-class="{ active: $state.current.name == 'document.view.activity' }">
|
</a>
|
||||||
<a href="#/document/view/{{ document.id }}/activity">
|
</li>
|
||||||
<span class="glyphicon glyphicon-tasks"></span> Activity
|
<li ng-class="{ active: $state.current.name == 'document.view.activity' }">
|
||||||
</a>
|
<a href="#/document/view/{{ document.id }}/activity">
|
||||||
</li>
|
<span class="glyphicon glyphicon-tasks"></span> Activity
|
||||||
</ul>
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div ui-view="tab"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<p class="page-header">
|
||||||
|
<span class="glyphicon glyphicon-comment"></span>
|
||||||
|
Comments
|
||||||
|
</p>
|
||||||
|
|
||||||
<div ui-view="tab"></div>
|
<div ng-show="!comments || comments.length == 0" class="text-center text-muted">
|
||||||
<div ui-view="file"></div>
|
<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" style="overflow: hidden">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form ng-submit="addComment()">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="sr-only" for="commentInput">Email address</label>
|
||||||
|
<input type="text" class="form-control" id="commentInput" ng-model="comment" placeholder="Add a comment">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
@ -1,3 +1,3 @@
|
|||||||
api.current_version=${project.version}
|
api.current_version=${project.version}
|
||||||
api.min_version=1.0
|
api.min_version=1.0
|
||||||
db.version=2
|
db.version=3
|
@ -1,3 +1,3 @@
|
|||||||
api.current_version=${project.version}
|
api.current_version=${project.version}
|
||||||
api.min_version=1.0
|
api.min_version=1.0
|
||||||
db.version=2
|
db.version=3
|
@ -12,7 +12,6 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the audit log resource.
|
* Test the audit log resource.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
package com.sismics.docs.rest;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
|
import javax.ws.rs.core.Form;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exhaustive test of the comment resource.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class TestCommentResource extends BaseJerseyTest {
|
||||||
|
/**
|
||||||
|
* Test the comment resource.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testCommentResource() throws Exception {
|
||||||
|
// Login comment1
|
||||||
|
clientUtil.createUser("comment1");
|
||||||
|
String comment1Token = clientUtil.login("comment1");
|
||||||
|
|
||||||
|
// Login comment2
|
||||||
|
clientUtil.createUser("comment2");
|
||||||
|
String comment2Token = clientUtil.login("comment2");
|
||||||
|
|
||||||
|
// Create a document with comment1
|
||||||
|
long create1Date = new Date().getTime();
|
||||||
|
JsonObject json = target().path("/document").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment1Token)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("title", "My super title document 1")
|
||||||
|
.param("description", "My super description for document 1")
|
||||||
|
.param("language", "eng")
|
||||||
|
.param("create_date", Long.toString(create1Date))), JsonObject.class);
|
||||||
|
String document1Id = json.getString("id");
|
||||||
|
Assert.assertNotNull(document1Id);
|
||||||
|
|
||||||
|
// Create a comment with comment2 (fail, no read access)
|
||||||
|
Response response = target().path("/comment").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment2Token)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("id", document1Id)
|
||||||
|
.param("content", "Comment by comment2")));
|
||||||
|
Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus()));
|
||||||
|
|
||||||
|
// Read comments with comment2 (fail, no read access)
|
||||||
|
response = target().path("/comment/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment2Token)
|
||||||
|
.get();
|
||||||
|
Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus()));
|
||||||
|
|
||||||
|
// Read comments with comment 1
|
||||||
|
json = target().path("/comment/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment1Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
Assert.assertEquals(0, json.getJsonArray("comments").size());
|
||||||
|
|
||||||
|
// Create a comment with comment1
|
||||||
|
json = target().path("/comment").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment1Token)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("id", document1Id)
|
||||||
|
.param("content", "Comment by comment1")), JsonObject.class);
|
||||||
|
String comment1Id = json.getString("id");
|
||||||
|
Assert.assertNotNull(comment1Id);
|
||||||
|
Assert.assertEquals("Comment by comment1", json.getString("content"));
|
||||||
|
Assert.assertEquals("comment1", json.getString("creator"));
|
||||||
|
Assert.assertNotNull(json.getJsonNumber("create_date"));
|
||||||
|
|
||||||
|
// Read comments with comment1
|
||||||
|
json = target().path("/comment/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment1Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
Assert.assertEquals(1, json.getJsonArray("comments").size());
|
||||||
|
Assert.assertEquals(comment1Id, json.getJsonArray("comments").getJsonObject(0).getString("id"));
|
||||||
|
|
||||||
|
// Delete a comment with comment2 (fail, no write access)
|
||||||
|
response = target().path("/comment/" + comment1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment2Token)
|
||||||
|
.delete();
|
||||||
|
Assert.assertEquals(Status.NOT_FOUND, Status.fromStatusCode(response.getStatus()));
|
||||||
|
|
||||||
|
// Delete a comment with comment1
|
||||||
|
json = target().path("/comment/" + comment1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment1Token)
|
||||||
|
.delete(JsonObject.class);
|
||||||
|
|
||||||
|
// Read comments with comment1
|
||||||
|
json = target().path("/comment/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment1Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
Assert.assertEquals(0, json.getJsonArray("comments").size());
|
||||||
|
|
||||||
|
// Add an ACL READ for comment2 with comment1
|
||||||
|
json = target().path("/acl").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment1Token)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("source", document1Id)
|
||||||
|
.param("perm", "READ")
|
||||||
|
.param("username", "comment2")), JsonObject.class);
|
||||||
|
|
||||||
|
// Create a comment with comment2
|
||||||
|
json = target().path("/comment").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment2Token)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("id", document1Id)
|
||||||
|
.param("content", "Comment by comment2")), JsonObject.class);
|
||||||
|
String comment2Id = json.getString("id");
|
||||||
|
|
||||||
|
// Read comments with comment2
|
||||||
|
json = target().path("/comment/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment2Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
Assert.assertEquals(1, json.getJsonArray("comments").size());
|
||||||
|
JsonObject comment = json.getJsonArray("comments").getJsonObject(0);
|
||||||
|
Assert.assertEquals(comment2Id, comment.getString("id"));
|
||||||
|
Assert.assertEquals("Comment by comment2", comment.getString("content"));
|
||||||
|
Assert.assertEquals("comment2", comment.getString("creator"));
|
||||||
|
Assert.assertNotNull(comment.getJsonNumber("create_date"));
|
||||||
|
|
||||||
|
// Delete a comment with comment2
|
||||||
|
json = target().path("/comment/" + comment2Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment2Token)
|
||||||
|
.delete(JsonObject.class);
|
||||||
|
|
||||||
|
// Read comments with comment2
|
||||||
|
json = target().path("/comment/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, comment2Token)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
Assert.assertEquals(0, json.getJsonArray("comments").size());
|
||||||
|
}
|
||||||
|
}
|
@ -26,8 +26,6 @@ import com.sismics.util.filter.TokenBasedSecurityFilter;
|
|||||||
import com.sismics.util.mime.MimeType;
|
import com.sismics.util.mime.MimeType;
|
||||||
import com.sismics.util.mime.MimeTypeUtil;
|
import com.sismics.util.mime.MimeTypeUtil;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exhaustive test of the document resource.
|
* Exhaustive test of the document resource.
|
||||||
*
|
*
|
||||||
|
@ -27,7 +27,6 @@ import com.sismics.util.filter.TokenBasedSecurityFilter;
|
|||||||
import com.sismics.util.mime.MimeType;
|
import com.sismics.util.mime.MimeType;
|
||||||
import com.sismics.util.mime.MimeTypeUtil;
|
import com.sismics.util.mime.MimeTypeUtil;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exhaustive test of the file resource.
|
* Exhaustive test of the file resource.
|
||||||
*
|
*
|
||||||
|
@ -20,7 +20,6 @@ import com.google.common.io.ByteStreams;
|
|||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exhaustive test of the share resource.
|
* Exhaustive test of the share resource.
|
||||||
*
|
*
|
||||||
|
@ -13,7 +13,6 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the tag resource.
|
* Test the tag resource.
|
||||||
*
|
*
|
||||||
|
@ -14,7 +14,6 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
import com.sismics.util.filter.TokenBasedSecurityFilter;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exhaustive test of the user resource.
|
* Exhaustive test of the user resource.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user