diff --git a/docs-web-common/src/main/java/com/sismics/rest/util/AclUtil.java b/docs-web-common/src/main/java/com/sismics/rest/util/AclUtil.java new file mode 100644 index 00000000..be467d8d --- /dev/null +++ b/docs-web-common/src/main/java/com/sismics/rest/util/AclUtil.java @@ -0,0 +1,49 @@ +package com.sismics.rest.util; + +import com.sismics.docs.core.constant.PermType; +import com.sismics.docs.core.dao.jpa.AclDao; +import com.sismics.docs.core.dao.jpa.dto.AclDto; +import com.sismics.security.IPrincipal; + +import javax.json.Json; +import javax.json.JsonArrayBuilder; +import javax.json.JsonObjectBuilder; +import java.util.List; + +/** + * Acl utilities. + * + * @author bgamard + */ +public class AclUtil { + /** + * Add ACLs to a JSON response. + * + * @param json JSON + * @param sourceId Source ID + * @param principal Principal + */ + public static void addAcls(JsonObjectBuilder json, String sourceId, IPrincipal principal) { + AclDao aclDao = new AclDao(); + List aclDtoList = aclDao.getBySourceId(sourceId); + JsonArrayBuilder aclList = Json.createArrayBuilder(); + boolean writable = false; + for (AclDto aclDto : aclDtoList) { + aclList.add(Json.createObjectBuilder() + .add("perm", aclDto.getPerm().name()) + .add("id", aclDto.getTargetId()) + .add("name", JsonUtil.nullable(aclDto.getTargetName())) + .add("type", aclDto.getTargetType())); + + if (!principal.isAnonymous() + && (aclDto.getTargetId().equals(principal.getId()) + || principal.getGroupIdSet().contains(aclDto.getTargetId())) + && aclDto.getPerm() == PermType.WRITE) { + // The source is writable for the current user + writable = true; + } + } + json.add("acls", aclList) + .add("writable", writable); + } +} diff --git a/docs-web-common/src/main/java/com/sismics/rest/util/JsonUtil.java b/docs-web-common/src/main/java/com/sismics/rest/util/JsonUtil.java index a244ef1a..039cc063 100644 --- a/docs-web-common/src/main/java/com/sismics/rest/util/JsonUtil.java +++ b/docs-web-common/src/main/java/com/sismics/rest/util/JsonUtil.java @@ -9,7 +9,6 @@ import javax.json.JsonValue; * @author bgamard */ public class JsonUtil { - /** * Returns a JsonValue from a String. * diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java index a7175486..b92197d7 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java @@ -25,6 +25,7 @@ import com.sismics.docs.core.util.jpa.SortCriteria; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; import com.sismics.rest.exception.ServerException; +import com.sismics.rest.util.AclUtil; import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; import com.sismics.util.mime.MimeType; @@ -110,28 +111,9 @@ public class DocumentResource extends BaseResource { document.add("coverage", JsonUtil.nullable(documentDto.getCoverage())); document.add("rights", JsonUtil.nullable(documentDto.getRights())); document.add("creator", documentDto.getCreator()); - + // Add ACL - List aclDtoList = aclDao.getBySourceId(documentId); - JsonArrayBuilder aclList = Json.createArrayBuilder(); - boolean writable = false; - for (AclDto aclDto : aclDtoList) { - aclList.add(Json.createObjectBuilder() - .add("perm", aclDto.getPerm().name()) - .add("id", aclDto.getTargetId()) - .add("name", JsonUtil.nullable(aclDto.getTargetName())) - .add("type", aclDto.getTargetType())); - - if (!principal.isAnonymous() - && (aclDto.getTargetId().equals(principal.getId()) - || principal.getGroupIdSet().contains(aclDto.getTargetId())) - && aclDto.getPerm() == PermType.WRITE) { - // The document is writable for the current user - writable = true; - } - } - document.add("acls", aclList) - .add("writable", writable); + AclUtil.addAcls(document, documentId, principal); // Add contributors ContributorDao contributorDao = new ContributorDao(); diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java index ee3990b3..0654d60f 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java @@ -5,12 +5,14 @@ import com.sismics.docs.core.constant.PermType; import com.sismics.docs.core.dao.jpa.AclDao; import com.sismics.docs.core.dao.jpa.TagDao; import com.sismics.docs.core.dao.jpa.criteria.TagCriteria; +import com.sismics.docs.core.dao.jpa.dto.AclDto; import com.sismics.docs.core.dao.jpa.dto.TagDto; import com.sismics.docs.core.model.jpa.Acl; import com.sismics.docs.core.model.jpa.Tag; import com.sismics.docs.core.util.jpa.SortCriteria; import com.sismics.rest.exception.ClientException; import com.sismics.rest.exception.ForbiddenClientException; +import com.sismics.rest.util.AclUtil; import com.sismics.rest.util.JsonUtil; import com.sismics.rest.util.ValidationUtil; import org.apache.commons.lang.StringUtils; @@ -73,6 +75,38 @@ public class TagResource extends BaseResource { return Response.ok().entity(response.build()).build(); } + /** + * Returns a tag. + * + * @param id Tag ID + * @return Response + */ + @GET + @Path("{id: [a-z0-9\\-]+}") + public Response get(@PathParam("id") String id) { + if (!authenticate()) { + throw new ForbiddenClientException(); + } + + TagDao tagDao = new TagDao(); + List tagDtoList = tagDao.findByCriteria(new TagCriteria().setTargetIdList(getTargetIdList(null)).setId(id), null); + if (tagDtoList.size() == 0) { + throw new NotFoundException(); + } + + // Add tag informatiosn + TagDto tagDto = tagDtoList.get(0); + JsonObjectBuilder tag = Json.createObjectBuilder() + .add("id", tagDto.getId()) + .add("name", tagDto.getName()) + .add("color", tagDto.getColor()); + + // Add ACL + AclUtil.addAcls(tag, id, principal); + + return Response.ok().entity(tag.build()).build(); + } + /** * Creates a new tag. * diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java index 0fd0746e..d5b4690a 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestAclResource.java @@ -291,6 +291,12 @@ public class TestAclResource extends BaseJerseyTest { JsonArray tags = json.getJsonArray("tags"); Assert.assertEquals(0, tags.size()); + // acltag2 cannot see tag1 + response = target().path("/tag/" + tag1Id).request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acltag2Token) + .get(); + Assert.assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); + // acltag2 cannot see any document json = target().path("/document/list") .queryParam("sort_column", 3) @@ -327,6 +333,13 @@ public class TestAclResource extends BaseJerseyTest { .param("target", "acltag2") .param("type", "USER")), JsonObject.class); + // acltag2 can see tag1 + json = target().path("/tag/" + tag1Id).request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acltag2Token) + .get(JsonObject.class); + Assert.assertFalse(json.getBoolean("writable")); + Assert.assertEquals(3, json.getJsonArray("acls").size()); + // acltag2 still cannot edit tag1 response = target().path("/tag/" + tag1Id).request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acltag2Token) @@ -379,6 +392,13 @@ public class TestAclResource extends BaseJerseyTest { .param("target", "acltag2") .param("type", "USER")), JsonObject.class); + // acltag2 can see and edit tag1 + json = target().path("/tag/" + tag1Id).request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acltag2Token) + .get(JsonObject.class); + Assert.assertTrue(json.getBoolean("writable")); + Assert.assertEquals(4, json.getJsonArray("acls").size()); + // acltag2 can edit tag1 target().path("/tag/" + tag1Id).request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, acltag2Token) diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java index eceac45d..ddbcbf29 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestTagResource.java @@ -46,6 +46,16 @@ public class TestTagResource extends BaseJerseyTest { .param("parent", tag3Id)), JsonObject.class); String tag4Id = json.getString("id"); Assert.assertNotNull(tag4Id); + + // Get the tag + json = target().path("/tag/" + tag4Id).request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, tag1Token) + .get(JsonObject.class); + Assert.assertEquals("Tag4", json.getString("name")); + Assert.assertEquals("#00ff00", json.getString("color")); + Assert.assertTrue(json.getBoolean("writable")); + JsonArray acls = json.getJsonArray("acls"); + Assert.assertEquals(2, acls.size()); // Create a tag with space (not allowed) Response response = target().path("/tag").request()