mirror of
https://github.com/sismics/docs.git
synced 2024-12-23 19:53:50 +01:00
commit
794c5012ad
@ -71,17 +71,22 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
/**
|
/**
|
||||||
* File view pager.
|
* File view pager.
|
||||||
*/
|
*/
|
||||||
ViewPager fileViewPager;
|
private ViewPager fileViewPager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File pager adapter.
|
* File pager adapter.
|
||||||
*/
|
*/
|
||||||
FilePagerAdapter filePagerAdapter;
|
private FilePagerAdapter filePagerAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document displayed.
|
* Document displayed.
|
||||||
*/
|
*/
|
||||||
JSONObject document;
|
private JSONObject document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menu.
|
||||||
|
*/
|
||||||
|
private Menu menu;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle args) {
|
protected void onCreate(final Bundle args) {
|
||||||
@ -181,12 +186,16 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
// Grab the attached files
|
// Grab the attached files
|
||||||
updateFiles();
|
updateFiles();
|
||||||
|
|
||||||
|
// Grab the full document (used for ACLs and writable status)
|
||||||
|
updateDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
MenuInflater inflater = getMenuInflater();
|
MenuInflater inflater = getMenuInflater();
|
||||||
inflater.inflate(R.menu.document_view_activity, menu);
|
inflater.inflate(R.menu.document_view_activity, menu);
|
||||||
|
this.menu = menu;
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,6 +502,33 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the document model.
|
||||||
|
*/
|
||||||
|
private void updateDocument() {
|
||||||
|
if (document == null) return;
|
||||||
|
|
||||||
|
// Silently get the document to know if it is writable by the current user
|
||||||
|
// If this call fails or is slow and the document is read-only,
|
||||||
|
// write actions will be allowed and will fail
|
||||||
|
DocumentResource.get(this, document.optString("id"), new JsonHttpResponseHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
|
boolean writable = response.optBoolean("writable");
|
||||||
|
|
||||||
|
if (menu != null) {
|
||||||
|
menu.findItem(R.id.share).setVisible(writable);
|
||||||
|
menu.findItem(R.id.upload_file).setVisible(writable);
|
||||||
|
menu.findItem(R.id.edit).setVisible(writable);
|
||||||
|
menu.findItem(R.id.delete_file).setVisible(writable);
|
||||||
|
menu.findItem(R.id.delete_document).setVisible(writable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Show the ACLs in a sliding panel from the right
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh files list.
|
* Refresh files list.
|
||||||
*/
|
*/
|
||||||
|
@ -15,6 +15,9 @@ import com.sismics.docs.event.ShareSendEvent;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,25 +29,33 @@ public class ShareListAdapter extends BaseAdapter {
|
|||||||
/**
|
/**
|
||||||
* Shares.
|
* Shares.
|
||||||
*/
|
*/
|
||||||
private JSONArray shares;
|
private List<JSONObject> acls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Share list adapter.
|
* Share list adapter.
|
||||||
*
|
*
|
||||||
* @param shares Shares
|
* @param acls ACLs
|
||||||
*/
|
*/
|
||||||
public ShareListAdapter(JSONArray shares) {
|
public ShareListAdapter(JSONArray acls) {
|
||||||
this.shares = shares;
|
this.acls = new ArrayList<>();
|
||||||
|
|
||||||
|
// Extract only share ACLs
|
||||||
|
for (int i = 0; i < acls.length(); i++) {
|
||||||
|
JSONObject acl = acls.optJSONObject(i);
|
||||||
|
if (acl.optString("type").equals("SHARE")) {
|
||||||
|
this.acls.add(acl);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return shares.length();
|
return acls.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject getItem(int position) {
|
public JSONObject getItem(int position) {
|
||||||
return shares.optJSONObject(position);
|
return acls.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -60,8 +71,8 @@ public class ShareListAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill the view
|
// Fill the view
|
||||||
final JSONObject share = getItem(position);
|
final JSONObject acl = getItem(position);
|
||||||
String name = share.optString("name");
|
String name = acl.optString("name");
|
||||||
TextView shareTextView = (TextView) view.findViewById(R.id.shareTextView);
|
TextView shareTextView = (TextView) view.findViewById(R.id.shareTextView);
|
||||||
shareTextView.setText(name.isEmpty() ? parent.getContext().getString(R.string.share_default_name) : name);
|
shareTextView.setText(name.isEmpty() ? parent.getContext().getString(R.string.share_default_name) : name);
|
||||||
|
|
||||||
@ -70,7 +81,7 @@ public class ShareListAdapter extends BaseAdapter {
|
|||||||
shareDeleteButton.setOnClickListener(new View.OnClickListener() {
|
shareDeleteButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
EventBus.getDefault().post(new ShareDeleteEvent(share.optString("id")));
|
EventBus.getDefault().post(new ShareDeleteEvent(acl.optString("id")));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,7 +90,7 @@ public class ShareListAdapter extends BaseAdapter {
|
|||||||
shareSendButton.setOnClickListener(new View.OnClickListener() {
|
shareSendButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
EventBus.getDefault().post(new ShareSendEvent(share));
|
EventBus.getDefault().post(new ShareSendEvent(acl));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -9,20 +9,20 @@ import org.json.JSONObject;
|
|||||||
*/
|
*/
|
||||||
public class ShareSendEvent {
|
public class ShareSendEvent {
|
||||||
/**
|
/**
|
||||||
* Share data.
|
* ACL data.
|
||||||
*/
|
*/
|
||||||
private JSONObject share;
|
private JSONObject acl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a share send event.
|
* Create a share send event.
|
||||||
*
|
*
|
||||||
* @param share Share data
|
* @param acl ACL data
|
||||||
*/
|
*/
|
||||||
public ShareSendEvent(JSONObject share) {
|
public ShareSendEvent(JSONObject acl) {
|
||||||
this.share = share;
|
this.acl = acl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject getShare() {
|
public JSONObject getAcl() {
|
||||||
return share;
|
return acl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,10 +125,10 @@ public class DocShareFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||||
document = response;
|
document = response;
|
||||||
JSONArray shares = response.optJSONArray("shares");
|
JSONArray acls = response.optJSONArray("acls");
|
||||||
shareProgressBar.setVisibility(View.GONE);
|
shareProgressBar.setVisibility(View.GONE);
|
||||||
shareListView.setEmptyView(shareEmptyView);
|
shareListView.setEmptyView(shareEmptyView);
|
||||||
shareListView.setAdapter(new ShareListAdapter(shares));
|
shareListView.setAdapter(new ShareListAdapter(acls));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -158,7 +158,7 @@ public class DocShareFragment extends DialogFragment {
|
|||||||
|
|
||||||
// Build the share link
|
// Build the share link
|
||||||
String serverUrl = PreferenceUtil.getServerUrl(getActivity());
|
String serverUrl = PreferenceUtil.getServerUrl(getActivity());
|
||||||
String link = serverUrl + "/share.html#/share/" + document.optString("id") + "/" + event.getShare().optString("id");
|
String link = serverUrl + "/share.html#/share/" + document.optString("id") + "/" + event.getAcl().optString("id");
|
||||||
|
|
||||||
// Build the intent
|
// Build the intent
|
||||||
Context context = getActivity();
|
Context context = getActivity();
|
||||||
|
@ -68,11 +68,29 @@ public class DocumentDao {
|
|||||||
* @param id Document ID
|
* @param id Document ID
|
||||||
* @return Document
|
* @return Document
|
||||||
*/
|
*/
|
||||||
public Document getDocument(String id) {
|
public DocumentDto getDocument(String id) {
|
||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
Query q = em.createQuery("select d from Document d where d.id = :id and d.deleteDate is null");
|
StringBuilder sb = new StringBuilder("select d.DOC_ID_C, d.DOC_TITLE_C, d.DOC_DESCRIPTION_C, d.DOC_CREATEDATE_D, d.DOC_LANGUAGE_C, ");
|
||||||
|
sb.append(" (select count(s.SHA_ID_C) from T_SHARE s, T_ACL ac where ac.ACL_SOURCEID_C = d.DOC_ID_C and ac.ACL_TARGETID_C = s.SHA_ID_C and ac.ACL_DELETEDATE_D is null and s.SHA_DELETEDATE_D is null), ");
|
||||||
|
sb.append(" (select count(f.FIL_ID_C) from T_FILE f where f.FIL_DELETEDATE_D is null and f.FIL_IDDOC_C = d.DOC_ID_C), ");
|
||||||
|
sb.append(" u.USE_USERNAME_C ");
|
||||||
|
sb.append(" from T_DOCUMENT d, T_USER u ");
|
||||||
|
sb.append(" where d.DOC_IDUSER_C = u.USE_ID_C and d.DOC_ID_C = :id and d.DOC_DELETEDATE_D is null ");
|
||||||
|
Query q = em.createNativeQuery(sb.toString());
|
||||||
q.setParameter("id", id);
|
q.setParameter("id", id);
|
||||||
return (Document) q.getSingleResult();
|
Object[] o = (Object[]) q.getSingleResult();
|
||||||
|
|
||||||
|
DocumentDto documentDto = new DocumentDto();
|
||||||
|
int i = 0;
|
||||||
|
documentDto.setId((String) o[i++]);
|
||||||
|
documentDto.setTitle((String) o[i++]);
|
||||||
|
documentDto.setDescription((String) o[i++]);
|
||||||
|
documentDto.setCreateTimestamp(((Timestamp) o[i++]).getTime());
|
||||||
|
documentDto.setLanguage((String) o[i++]);
|
||||||
|
documentDto.setShared(((Number) o[i++]).intValue() > 0);
|
||||||
|
documentDto.setFileCount(((Number) o[i++]).intValue());
|
||||||
|
documentDto.setCreator((String) o[i++]);
|
||||||
|
return documentDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,16 +75,18 @@ public class TagDao {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public List<TagDto> getByDocumentId(String documentId) {
|
public List<TagDto> getByDocumentId(String documentId, String userId) {
|
||||||
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
EntityManager em = ThreadLocalContext.get().getEntityManager();
|
||||||
StringBuilder sb = new StringBuilder("select t.TAG_ID_C, t.TAG_NAME_C, t.TAG_COLOR_C from T_DOCUMENT_TAG dt ");
|
StringBuilder sb = new StringBuilder("select t.TAG_ID_C, t.TAG_NAME_C, t.TAG_COLOR_C from T_DOCUMENT_TAG dt ");
|
||||||
sb.append(" join T_TAG t on t.TAG_ID_C = dt.DOT_IDTAG_C ");
|
sb.append(" join T_TAG t on t.TAG_ID_C = dt.DOT_IDTAG_C ");
|
||||||
sb.append(" where dt.DOT_IDDOCUMENT_C = :documentId and t.TAG_DELETEDATE_D is null ");
|
sb.append(" where dt.DOT_IDDOCUMENT_C = :documentId and t.TAG_DELETEDATE_D is null ");
|
||||||
|
sb.append(" and t.TAG_IDUSER_C = :userId ");
|
||||||
sb.append(" order by t.TAG_NAME_C ");
|
sb.append(" order by t.TAG_NAME_C ");
|
||||||
|
|
||||||
// Perform the query
|
// Perform the query
|
||||||
Query q = em.createNativeQuery(sb.toString());
|
Query q = em.createNativeQuery(sb.toString());
|
||||||
q.setParameter("documentId", documentId);
|
q.setParameter("documentId", documentId);
|
||||||
|
q.setParameter("userId", userId);
|
||||||
List<Object[]> l = q.getResultList();
|
List<Object[]> l = q.getResultList();
|
||||||
|
|
||||||
// Assemble results
|
// Assemble results
|
||||||
|
@ -44,6 +44,11 @@ public class DocumentDto {
|
|||||||
*/
|
*/
|
||||||
private Integer fileCount;
|
private Integer fileCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Document creator.
|
||||||
|
*/
|
||||||
|
private String creator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter de id.
|
* Getter de id.
|
||||||
*
|
*
|
||||||
@ -167,4 +172,20 @@ public class DocumentDto {
|
|||||||
public void setFileCount(Integer fileCount) {
|
public void setFileCount(Integer fileCount) {
|
||||||
this.fileCount = fileCount;
|
this.fileCount = fileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of creator.
|
||||||
|
* @return creator
|
||||||
|
*/
|
||||||
|
public String getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter of creator.
|
||||||
|
* @param creator creator
|
||||||
|
*/
|
||||||
|
public void setCreator(String creator) {
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ public class AclResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate input
|
// Validate input
|
||||||
sourceId = ValidationUtil.validateLength(sourceId, "source", 36, 36, false);
|
ValidationUtil.validateRequired(sourceId, "source");
|
||||||
PermType perm = PermType.valueOf(ValidationUtil.validateLength(permStr, "perm", 1, 30, false));
|
PermType perm = PermType.valueOf(ValidationUtil.validateLength(permStr, "perm", 1, 30, false));
|
||||||
username = ValidationUtil.validateLength(username, "username", 1, 50, false);
|
username = ValidationUtil.validateLength(username, "username", 1, 50, false);
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ public class AclResource extends BaseResource {
|
|||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{sourceId: [a-z0-9\\-]+}/{perm: READ|WRITE}/{targetId: [a-z0-9\\-]+}")
|
@Path("{sourceId: [a-z0-9\\-]+}/{perm: [A-Z]+}/{targetId: [a-z0-9\\-]+}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response delete(
|
public Response delete(
|
||||||
@PathParam("sourceId") String sourceId,
|
@PathParam("sourceId") String sourceId,
|
||||||
@ -116,9 +116,9 @@ public class AclResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate input
|
// Validate input
|
||||||
sourceId = ValidationUtil.validateLength(sourceId, "source", 36, 36, false);
|
ValidationUtil.validateRequired(sourceId, "source");
|
||||||
PermType perm = PermType.valueOf(ValidationUtil.validateLength(permStr, "perm", 1, 30, false));
|
PermType perm = PermType.valueOf(ValidationUtil.validateLength(permStr, "perm", 1, 30, false));
|
||||||
targetId = ValidationUtil.validateLength(targetId, "target", 36, 36, false);
|
ValidationUtil.validateRequired(targetId, "target");
|
||||||
|
|
||||||
// Check permission on the source by the principal
|
// Check permission on the source by the principal
|
||||||
AclDao aclDao = new AclDao();
|
AclDao aclDao = new AclDao();
|
||||||
|
@ -38,7 +38,6 @@ import com.sismics.docs.core.dao.jpa.AclDao;
|
|||||||
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
||||||
import com.sismics.docs.core.dao.jpa.FileDao;
|
import com.sismics.docs.core.dao.jpa.FileDao;
|
||||||
import com.sismics.docs.core.dao.jpa.TagDao;
|
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.criteria.DocumentCriteria;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.AclDto;
|
import com.sismics.docs.core.dao.jpa.dto.AclDto;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
||||||
@ -84,10 +83,9 @@ public class DocumentResource extends BaseResource {
|
|||||||
|
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
AclDao aclDao = new AclDao();
|
AclDao aclDao = new AclDao();
|
||||||
UserDao userDao = new UserDao();
|
DocumentDto documentDto;
|
||||||
Document documentDb;
|
|
||||||
try {
|
try {
|
||||||
documentDb = documentDao.getDocument(documentId);
|
documentDto = documentDao.getDocument(documentId);
|
||||||
|
|
||||||
// Check document visibility
|
// Check document visibility
|
||||||
if (!aclDao.checkPermission(documentId, PermType.READ, shareId == null ? principal.getId() : shareId)) {
|
if (!aclDao.checkPermission(documentId, PermType.READ, shareId == null ? principal.getId() : shareId)) {
|
||||||
@ -98,16 +96,21 @@ public class DocumentResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSONObject document = new JSONObject();
|
JSONObject document = new JSONObject();
|
||||||
document.put("id", documentDb.getId());
|
document.put("id", documentDto.getId());
|
||||||
document.put("title", documentDb.getTitle());
|
document.put("title", documentDto.getTitle());
|
||||||
document.put("description", documentDb.getDescription());
|
document.put("description", documentDto.getDescription());
|
||||||
document.put("create_date", documentDb.getCreateDate().getTime());
|
document.put("create_date", documentDto.getCreateTimestamp());
|
||||||
document.put("language", documentDb.getLanguage());
|
document.put("language", documentDto.getLanguage());
|
||||||
document.put("creator", userDao.getById(documentDb.getUserId()).getUsername());
|
document.put("shared", documentDto.getShared());
|
||||||
|
document.put("file_count", documentDto.getFileCount());
|
||||||
|
|
||||||
// Add tags
|
if (principal.isAnonymous()) {
|
||||||
|
// No tags in anonymous mode (sharing)
|
||||||
|
document.put("tags", new ArrayList<JSONObject>());
|
||||||
|
} else {
|
||||||
|
// Add tags added by the current user on this document
|
||||||
TagDao tagDao = new TagDao();
|
TagDao tagDao = new TagDao();
|
||||||
List<TagDto> tagDtoList = tagDao.getByDocumentId(documentId);
|
List<TagDto> tagDtoList = tagDao.getByDocumentId(documentId, principal.getId());
|
||||||
List<JSONObject> tags = new ArrayList<>();
|
List<JSONObject> tags = new ArrayList<>();
|
||||||
for (TagDto tagDto : tagDtoList) {
|
for (TagDto tagDto : tagDtoList) {
|
||||||
JSONObject tag = new JSONObject();
|
JSONObject tag = new JSONObject();
|
||||||
@ -117,6 +120,11 @@ public class DocumentResource extends BaseResource {
|
|||||||
tags.add(tag);
|
tags.add(tag);
|
||||||
}
|
}
|
||||||
document.put("tags", tags);
|
document.put("tags", tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Below is specific to GET /document/id
|
||||||
|
|
||||||
|
document.put("creator", documentDto.getCreator());
|
||||||
|
|
||||||
// Add ACL
|
// Add ACL
|
||||||
List<AclDto> aclDtoList = aclDao.getBySourceId(documentId);
|
List<AclDto> aclDtoList = aclDao.getBySourceId(documentId);
|
||||||
@ -130,7 +138,10 @@ public class DocumentResource extends BaseResource {
|
|||||||
acl.put("type", aclDto.getTargetType());
|
acl.put("type", aclDto.getTargetType());
|
||||||
aclList.add(acl);
|
aclList.add(acl);
|
||||||
|
|
||||||
if (aclDto.getTargetId().equals(principal.getId()) && aclDto.getPerm() == PermType.WRITE) {
|
if (!principal.isAnonymous()
|
||||||
|
&& aclDto.getTargetId().equals(principal.getId())
|
||||||
|
&& aclDto.getPerm() == PermType.WRITE) {
|
||||||
|
// The document is writable for the current user
|
||||||
writable = true;
|
writable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,12 +193,12 @@ public class DocumentResource extends BaseResource {
|
|||||||
document.put("title", documentDto.getTitle());
|
document.put("title", documentDto.getTitle());
|
||||||
document.put("description", documentDto.getDescription());
|
document.put("description", documentDto.getDescription());
|
||||||
document.put("create_date", documentDto.getCreateTimestamp());
|
document.put("create_date", documentDto.getCreateTimestamp());
|
||||||
document.put("shared", documentDto.getShared());
|
|
||||||
document.put("language", documentDto.getLanguage());
|
document.put("language", documentDto.getLanguage());
|
||||||
|
document.put("shared", documentDto.getShared());
|
||||||
document.put("file_count", documentDto.getFileCount());
|
document.put("file_count", documentDto.getFileCount());
|
||||||
|
|
||||||
// Get tags
|
// Get tags added by the current user on this document
|
||||||
List<TagDto> tagDtoList = tagDao.getByDocumentId(documentDto.getId());
|
List<TagDto> tagDtoList = tagDao.getByDocumentId(documentDto.getId(), principal.getId());
|
||||||
List<JSONObject> tags = new ArrayList<>();
|
List<JSONObject> tags = new ArrayList<>();
|
||||||
for (TagDto tagDto : tagDtoList) {
|
for (TagDto tagDto : tagDtoList) {
|
||||||
JSONObject tag = new JSONObject();
|
JSONObject tag = new JSONObject();
|
||||||
|
@ -41,6 +41,7 @@ import com.sismics.docs.core.dao.jpa.AclDao;
|
|||||||
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
import com.sismics.docs.core.dao.jpa.DocumentDao;
|
||||||
import com.sismics.docs.core.dao.jpa.FileDao;
|
import com.sismics.docs.core.dao.jpa.FileDao;
|
||||||
import com.sismics.docs.core.dao.jpa.UserDao;
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
||||||
import com.sismics.docs.core.event.FileCreatedAsyncEvent;
|
import com.sismics.docs.core.event.FileCreatedAsyncEvent;
|
||||||
import com.sismics.docs.core.event.FileDeletedAsyncEvent;
|
import com.sismics.docs.core.event.FileDeletedAsyncEvent;
|
||||||
import com.sismics.docs.core.model.context.AppContext;
|
import com.sismics.docs.core.model.context.AppContext;
|
||||||
@ -486,9 +487,9 @@ public class FileResource extends BaseResource {
|
|||||||
|
|
||||||
// Get the document
|
// Get the document
|
||||||
DocumentDao documentDao = new DocumentDao();
|
DocumentDao documentDao = new DocumentDao();
|
||||||
Document document;
|
DocumentDto documentDto;
|
||||||
try {
|
try {
|
||||||
document = documentDao.getDocument(documentId);
|
documentDto = documentDao.getDocument(documentId);
|
||||||
|
|
||||||
// Check document visibility
|
// Check document visibility
|
||||||
AclDao aclDao = new AclDao();
|
AclDao aclDao = new AclDao();
|
||||||
@ -537,7 +538,7 @@ public class FileResource extends BaseResource {
|
|||||||
// Write to the output
|
// Write to the output
|
||||||
return Response.ok(stream)
|
return Response.ok(stream)
|
||||||
.header("Content-Type", "application/zip")
|
.header("Content-Type", "application/zip")
|
||||||
.header("Content-Disposition", "attachment; filename=\"" + document.getTitle().replaceAll("\\W+", "_") + ".zip\"")
|
.header("Content-Disposition", "attachment; filename=\"" + documentDto.getTitle().replaceAll("\\W+", "_") + ".zip\"")
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,6 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* File has been drag & dropped.
|
* File has been drag & dropped.
|
||||||
* @param files
|
|
||||||
*/
|
*/
|
||||||
$scope.fileDropped = function(files) {
|
$scope.fileDropped = function(files) {
|
||||||
if (!$scope.document.writable) {
|
if (!$scope.document.writable) {
|
||||||
@ -186,8 +185,6 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Upload a file.
|
* Upload a file.
|
||||||
* @param file
|
|
||||||
* @param newfile
|
|
||||||
*/
|
*/
|
||||||
$scope.uploadFile = function(file, newfile) {
|
$scope.uploadFile = function(file, newfile) {
|
||||||
// Upload the file
|
// Upload the file
|
||||||
@ -210,7 +207,6 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an ACL.
|
* Delete an ACL.
|
||||||
* @param acl
|
|
||||||
*/
|
*/
|
||||||
$scope.deleteAcl = function(acl) {
|
$scope.deleteAcl = function(acl) {
|
||||||
Restangular.one('acl/' + $stateParams.id + '/' + acl.perm + '/' + acl.id, null).remove().then(function () {
|
Restangular.one('acl/' + $stateParams.id + '/' + acl.perm + '/' + acl.id, null).remove().then(function () {
|
||||||
@ -224,17 +220,45 @@ angular.module('docs').controller('DocumentView', function ($scope, $state, $sta
|
|||||||
* Add an ACL.
|
* Add an ACL.
|
||||||
*/
|
*/
|
||||||
$scope.addAcl = function() {
|
$scope.addAcl = function() {
|
||||||
|
// Compute ACLs to add
|
||||||
$scope.acl.source = $stateParams.id;
|
$scope.acl.source = $stateParams.id;
|
||||||
Restangular.one('acl').put($scope.acl).then(function(acl) {
|
var acls = [];
|
||||||
$scope.acl = { perm: 'READ' };
|
if ($scope.acl.perm == 'READWRITE') {
|
||||||
|
acls = [{
|
||||||
|
source: $stateParams.id,
|
||||||
|
username: $scope.acl.username,
|
||||||
|
perm: 'READ'
|
||||||
|
}, {
|
||||||
|
source: $stateParams.id,
|
||||||
|
username: $scope.acl.username,
|
||||||
|
perm: 'WRITE'
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
acls = [{
|
||||||
|
source: $stateParams.id,
|
||||||
|
username: $scope.acl.username,
|
||||||
|
perm: $scope.acl.perm
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add ACLs
|
||||||
|
_.each(acls, function(acl) {
|
||||||
|
Restangular.one('acl').put(acl).then(function(acl) {
|
||||||
if (_.isUndefined(acl.id)) {
|
if (_.isUndefined(acl.id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$scope.document.acls.push(acl);
|
$scope.document.acls.push(acl);
|
||||||
$scope.document.acls = angular.copy($scope.document.acls);
|
$scope.document.acls = angular.copy($scope.document.acls);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset form
|
||||||
|
$scope.acl = { perm: 'READ' };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-complete on ACL target.
|
||||||
|
*/
|
||||||
$scope.getTargetAclTypeahead = function($viewValue) {
|
$scope.getTargetAclTypeahead = function($viewValue) {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
Restangular.one('acl/target/search')
|
Restangular.one('acl/target/search')
|
||||||
|
@ -92,7 +92,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<span class="label label-default" style="margin-right: 6px;" ng-repeat="a in acl | orderBy: 'perm'">
|
<span class="label label-default" style="margin-right: 6px;" ng-repeat="a in acl | orderBy: 'perm'">
|
||||||
{{ a.perm }}
|
{{ a.perm }}
|
||||||
<span ng-show="document.creator != a.name && a.type == 'USER' && document.writable"
|
<span ng-show="(document.creator != a.name && a.type == 'USER' || a.type != 'USER') && document.writable"
|
||||||
class="glyphicon glyphicon-remove pointer"
|
class="glyphicon glyphicon-remove pointer"
|
||||||
ng-click="deleteAcl(a)"></span>
|
ng-click="deleteAcl(a)"></span>
|
||||||
</span>
|
</span>
|
||||||
@ -118,8 +118,8 @@
|
|||||||
<label class=" col-sm-2 control-label" for="inputPermission">Permission</label>
|
<label class=" col-sm-2 control-label" for="inputPermission">Permission</label>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
<select class="form-control" ng-model="acl.perm" id="inputPermission">
|
<select class="form-control" ng-model="acl.perm" id="inputPermission">
|
||||||
<option value="READ">Read</option>
|
<option value="READ">Can read</option>
|
||||||
<option value="WRITE">Write</option>
|
<option value="READWRITE">Can edit</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -138,8 +138,8 @@ public class TestDocumentResource extends BaseJerseyTest {
|
|||||||
postParams.add("title", "My super title document 1");
|
postParams.add("title", "My super title document 1");
|
||||||
postParams.add("description", "My super description for document 1");
|
postParams.add("description", "My super description for document 1");
|
||||||
postParams.add("language", "eng");
|
postParams.add("language", "eng");
|
||||||
create1Date = new Date().getTime();
|
long create3Date = new Date().getTime();
|
||||||
postParams.add("create_date", create1Date);
|
postParams.add("create_date", create3Date);
|
||||||
response = documentResource.put(ClientResponse.class, postParams);
|
response = documentResource.put(ClientResponse.class, postParams);
|
||||||
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
json = response.getEntity(JSONObject.class);
|
json = response.getEntity(JSONObject.class);
|
||||||
@ -148,14 +148,14 @@ public class TestDocumentResource extends BaseJerseyTest {
|
|||||||
|
|
||||||
// Add a file
|
// Add a file
|
||||||
fileResource = resource().path("/file");
|
fileResource = resource().path("/file");
|
||||||
fileResource.addFilter(new CookieAuthenticationFilter(document1Token));
|
fileResource.addFilter(new CookieAuthenticationFilter(document3Token));
|
||||||
form = new FormDataMultiPart();
|
form = new FormDataMultiPart();
|
||||||
file = this.getClass().getResourceAsStream("/file/Einstein-Roosevelt-letter.png");
|
file = this.getClass().getResourceAsStream("/file/Einstein-Roosevelt-letter.png");
|
||||||
fdp = new FormDataBodyPart("file",
|
fdp = new FormDataBodyPart("file",
|
||||||
new BufferedInputStream(file),
|
new BufferedInputStream(file),
|
||||||
MediaType.APPLICATION_OCTET_STREAM_TYPE);
|
MediaType.APPLICATION_OCTET_STREAM_TYPE);
|
||||||
form.bodyPart(fdp);
|
form.bodyPart(fdp);
|
||||||
form.field("id", document1Id);
|
form.field("id", document3Id);
|
||||||
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form);
|
response = fileResource.type(MediaType.MULTIPART_FORM_DATA).put(ClientResponse.class, form);
|
||||||
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
json = response.getEntity(JSONObject.class);
|
json = response.getEntity(JSONObject.class);
|
||||||
@ -206,6 +206,13 @@ public class TestDocumentResource extends BaseJerseyTest {
|
|||||||
json = response.getEntity(JSONObject.class);
|
json = response.getEntity(JSONObject.class);
|
||||||
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
Assert.assertEquals(Status.OK, Status.fromStatusCode(response.getStatus()));
|
||||||
Assert.assertEquals(document1Id, json.getString("id"));
|
Assert.assertEquals(document1Id, json.getString("id"));
|
||||||
|
Assert.assertEquals("document1", json.getString("creator"));
|
||||||
|
Assert.assertEquals(1, json.getInt("file_count"));
|
||||||
|
Assert.assertEquals(true, json.getBoolean("shared"));
|
||||||
|
Assert.assertEquals("My super title document 1", json.getString("title"));
|
||||||
|
Assert.assertEquals("My super description for document 1", json.getString("description"));
|
||||||
|
Assert.assertEquals("eng", json.getString("language"));
|
||||||
|
Assert.assertEquals(create1Date, json.getLong("create_date"));
|
||||||
tags = json.getJSONArray("tags");
|
tags = json.getJSONArray("tags");
|
||||||
Assert.assertEquals(1, tags.length());
|
Assert.assertEquals(1, tags.length());
|
||||||
Assert.assertEquals(tag1Id, tags.getJSONObject(0).getString("id"));
|
Assert.assertEquals(tag1Id, tags.getJSONObject(0).getString("id"));
|
||||||
|
Loading…
Reference in New Issue
Block a user