docs/docs-web/src/main/java/com/sismics/docs/rest/resource/TagResource.java
2018-01-31 22:07:38 +01:00

342 lines
11 KiB
Java

package com.sismics.docs.rest.resource;
import com.google.common.collect.Sets;
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.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.ValidationUtil;
import org.apache.commons.lang.StringUtils;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import java.text.MessageFormat;
import java.util.List;
import java.util.Set;
/**
* Tag REST resources.
*
* @author bgamard
*/
@Path("/tag")
public class TagResource extends BaseResource {
/**
* Returns the list of all visible tags.
*
* @api {get} /tag/list Get tags
* @apiName GetTagList
* @apiGroup Tag
* @apiSuccess {Object[]} tags List of tags
* @apiSuccess {String} tags.id ID
* @apiSuccess {String} tags.name Name
* @apiSuccess {String} tags.color Color
* @apiSuccess {String} tags.parent Parent
* @apiError (client) ForbiddenError Access denied
* @apiPermission user
* @apiVersion 1.5.0
*
* @return Response
*/
@GET
@Path("/list")
public Response list() {
if (!authenticate()) {
throw new ForbiddenClientException();
}
TagDao tagDao = new TagDao();
List<TagDto> tagDtoList = tagDao.findByCriteria(new TagCriteria().setTargetIdList(getTargetIdList(null)), new SortCriteria(1, true));
// Extract tag IDs
Set<String> tagIdSet = Sets.newHashSet();
for (TagDto tagDto : tagDtoList) {
tagIdSet.add(tagDto.getId());
}
// Build the response
JsonArrayBuilder items = Json.createArrayBuilder();
for (TagDto tagDto : tagDtoList) {
JsonObjectBuilder item = Json.createObjectBuilder()
.add("id", tagDto.getId())
.add("name", tagDto.getName())
.add("color", tagDto.getColor());
if (tagIdSet.contains(tagDto.getParentId())) {
item.add("parent", tagDto.getParentId());
}
items.add(item);
}
JsonObjectBuilder response = Json.createObjectBuilder()
.add("tags", items);
return Response.ok().entity(response.build()).build();
}
/**
* Returns a tag.
*
* @api {get} /tag/:id Get a tag
* @apiName GetTag
* @apiGroup Tag
* @apiSuccess {String} id ID
* @apiSuccess {String} name Name
* @apiSuccess {String} creator Username of the creator
* @apiSuccess {String} color Color
* @apiSuccess {String} parent Parent
* @apiSuccess {Boolean} writable True if the tag is writable by the current user
* @apiSuccess {Object[]} acls List of ACL
* @apiSuccess {String} acls.id ID
* @apiSuccess {String="READ","WRITE"} acls.perm Permission
* @apiSuccess {String} acls.name Target name
* @apiSuccess {String="USER","GROUP","SHARE"} acls.type Target type
* @apiError (client) ForbiddenError Access denied
* @apiError (client) NotFound Tag not found
* @apiPermission user
* @apiVersion 1.5.0
*
* @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<TagDto> tagDtoList = tagDao.findByCriteria(new TagCriteria().setTargetIdList(getTargetIdList(null)).setId(id), null);
if (tagDtoList.isEmpty()) {
throw new NotFoundException();
}
// Add tag informatiosn
TagDto tagDto = tagDtoList.get(0);
JsonObjectBuilder tag = Json.createObjectBuilder()
.add("id", tagDto.getId())
.add("creator", tagDto.getCreator())
.add("name", tagDto.getName())
.add("color", tagDto.getColor());
// Add the parent if its visible
if (tagDto.getParentId() != null) {
AclDao aclDao = new AclDao();
if (aclDao.checkPermission(tagDto.getParentId(), PermType.READ, getTargetIdList(null))) {
tag.add("parent", tagDto.getParentId());
}
}
// Add ACL
AclUtil.addAcls(tag, id, getTargetIdList(null));
return Response.ok().entity(tag.build()).build();
}
/**
* Creates a new tag.
*
* @api {put} /tag Create a tag
* @apiName PutTag
* @apiGroup Tag
* @apiParam {String} name Name
* @apiParam {String} color Color
* @apiParam {String} parent Parent ID
* @apiSuccess {String} id Tag ID
* @apiError (client) ForbiddenError Access denied
* @apiError (client) ValidationError Validation error
* @apiError (client) SpacesNotAllowed Spaces are not allowed in tag name
* @apiError (client) ParentNotFound Parent not found
* @apiPermission user
* @apiVersion 1.5.0
*
* @param name Name
* @param color Color
* @param parentId Parent ID
* @return Response
*/
@PUT
public Response add(
@FormParam("name") String name,
@FormParam("color") String color,
@FormParam("parent") String parentId) {
if (!authenticate()) {
throw new ForbiddenClientException();
}
// Validate input data
name = ValidationUtil.validateLength(name, "name", 1, 36, false);
ValidationUtil.validateHexColor(color, "color", true);
// Don't allow spaces
if (name.contains(" ")) {
throw new ClientException("SpacesNotAllowed", "Spaces are not allowed in tag name");
}
// Check the parent
if (StringUtils.isEmpty(parentId)) {
parentId = null;
} else {
AclDao aclDao = new AclDao();
if (!aclDao.checkPermission(parentId, PermType.READ, getTargetIdList(null))) {
throw new ClientException("ParentNotFound", MessageFormat.format("Parent not found: {0}", parentId));
}
}
// Create the tag
TagDao tagDao = new TagDao();
Tag tag = new Tag();
tag.setName(name);
tag.setColor(color);
tag.setUserId(principal.getId());
tag.setParentId(parentId);
String id = tagDao.create(tag, principal.getId());
// Create read ACL
AclDao aclDao = new AclDao();
Acl acl = new Acl();
acl.setPerm(PermType.READ);
acl.setSourceId(id);
acl.setTargetId(principal.getId());
aclDao.create(acl, principal.getId());
// Create write ACL
acl = new Acl();
acl.setPerm(PermType.WRITE);
acl.setSourceId(id);
acl.setTargetId(principal.getId());
aclDao.create(acl, principal.getId());
JsonObjectBuilder response = Json.createObjectBuilder()
.add("id", id);
return Response.ok().entity(response.build()).build();
}
/**
* Update a tag.
*
* @api {post} /tag/:id Update a tag
* @apiName PostTag
* @apiGroup Tag
* @apiParam {String} id Tag ID
* @apiParam {String} name Name
* @apiParam {String} color Color
* @apiParam {String} parent Parent ID
* @apiSuccess {String} id Tag ID
* @apiError (client) ForbiddenError Access denied
* @apiError (client) ValidationError Validation error
* @apiError (client) SpacesNotAllowed Spaces are not allowed in tag name
* @apiError (client) ParentNotFound Parent not found
* @apiError (client) NotFound Tag not found
* @apiPermission user
* @apiVersion 1.5.0
*
* @param name Name
* @param color Color
* @param parentId Parent ID
* @return Response
*/
@POST
@Path("{id: [a-z0-9\\-]+}")
public Response update(
@PathParam("id") String id,
@FormParam("name") String name,
@FormParam("color") String color,
@FormParam("parent") String parentId) {
if (!authenticate()) {
throw new ForbiddenClientException();
}
// Validate input data
name = ValidationUtil.validateLength(name, "name", 1, 36, true);
ValidationUtil.validateHexColor(color, "color", true);
// Don't allow spaces
if (name.contains(" ")) {
throw new ClientException("SpacesNotAllowed", "Spaces are not allowed in tag name");
}
// Check permission
AclDao aclDao = new AclDao();
if (!aclDao.checkPermission(id, PermType.WRITE, getTargetIdList(null))) {
throw new NotFoundException();
}
// Check the parent
if (StringUtils.isEmpty(parentId)) {
parentId = null;
} else {
if (!aclDao.checkPermission(parentId, PermType.READ, getTargetIdList(null))) {
throw new ClientException("ParentNotFound", MessageFormat.format("Parent not found: {0}", parentId));
}
}
// Update the tag
TagDao tagDao = new TagDao();
Tag tag = tagDao.getById(id);
if (!StringUtils.isEmpty(name)) {
tag.setName(name);
}
if (!StringUtils.isEmpty(color)) {
tag.setColor(color);
}
// Parent tag is always updated to have the possibility to delete it
tag.setParentId(parentId);
tagDao.update(tag, principal.getId());
JsonObjectBuilder response = Json.createObjectBuilder()
.add("id", id);
return Response.ok().entity(response.build()).build();
}
/**
* Delete a tag.
*
* @api {delete} /tag/:id Delete a tag
* @apiName DeleteTag
* @apiGroup Tag
* @apiParam {String} id Tag ID
* @apiSuccess {String} status Status OK
* @apiError (client) ForbiddenError Access denied
* @apiError (client) NotFound Tag not found
* @apiPermission user
* @apiVersion 1.5.0
*
* @param id Tag ID
* @return Response
*/
@DELETE
@Path("{id: [a-z0-9\\-]+}")
public Response delete(
@PathParam("id") String id) {
if (!authenticate()) {
throw new ForbiddenClientException();
}
// Get the tag
AclDao aclDao = new AclDao();
if (!aclDao.checkPermission(id, PermType.WRITE, getTargetIdList(null))) {
throw new NotFoundException();
}
// Delete the tag
TagDao tagDao = new TagDao();
tagDao.delete(id, principal.getId());
// Always return OK
JsonObjectBuilder response = Json.createObjectBuilder()
.add("status", "ok");
return Response.ok().entity(response.build()).build();
}
}