Merge pull request #19 from sismics/master

Fix post-ACL system
This commit is contained in:
Benjamin Gamard 2015-05-10 14:03:44 +02:00
commit 794c5012ad
13 changed files with 209 additions and 78 deletions

View File

@ -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.
*/ */

View File

@ -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));
} }
}); });

View File

@ -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;
} }
} }

View File

@ -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();

View File

@ -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;
} }
/** /**

View File

@ -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

View File

@ -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;
}
} }

View File

@ -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();

View File

@ -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();

View File

@ -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();
} }
} }

View File

@ -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')

View File

@ -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>

View File

@ -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"));