1
0
mirror of https://github.com/sismics/docs.git synced 2025-12-13 09:46:17 +00:00

#159: validate route steps

This commit is contained in:
Benjamin Gamard
2018-02-01 18:01:11 +01:00
parent c9adff5a25
commit 2b4ddfa072
14 changed files with 352 additions and 91 deletions

View File

@@ -13,9 +13,11 @@ import com.sismics.docs.core.event.DocumentCreatedAsyncEvent;
import com.sismics.docs.core.event.DocumentDeletedAsyncEvent;
import com.sismics.docs.core.event.DocumentUpdatedAsyncEvent;
import com.sismics.docs.core.event.FileDeletedAsyncEvent;
import com.sismics.docs.core.model.jpa.*;
import com.sismics.docs.core.model.jpa.Acl;
import com.sismics.docs.core.model.jpa.Document;
import com.sismics.docs.core.model.jpa.File;
import com.sismics.docs.core.model.jpa.User;
import com.sismics.docs.core.util.PdfUtil;
import com.sismics.docs.core.util.RoutingUtil;
import com.sismics.docs.core.util.jpa.PaginatedList;
import com.sismics.docs.core.util.jpa.PaginatedLists;
import com.sismics.docs.core.util.jpa.SortCriteria;
@@ -212,12 +214,12 @@ public class DocumentResource extends BaseResource {
document.add("relations", relationList);
// Add current route step
RouteStep routeStep = RoutingUtil.getCurrentStep(documentId);
if (routeStep != null && !principal.isAnonymous()) {
RouteStepDto routeStepDto = new RouteStepDao().getCurrentStep(documentId);
if (routeStepDto != null && !principal.isAnonymous()) {
document.add("route_step", Json.createObjectBuilder()
.add("name", routeStep.getName())
.add("type", routeStep.getType().name())
.add("transitionable", getTargetIdList(null).contains(routeStep.getTargetId())));
.add("name", routeStepDto.getName())
.add("type", routeStepDto.getType().name())
.add("transitionable", getTargetIdList(null).contains(routeStepDto.getTargetId())));
}
return Response.ok().entity(document.build()).build();

View File

@@ -2,11 +2,13 @@ package com.sismics.docs.rest.resource;
import com.sismics.docs.core.constant.AclTargetType;
import com.sismics.docs.core.constant.PermType;
import com.sismics.docs.core.constant.RouteStepTransition;
import com.sismics.docs.core.constant.RouteStepType;
import com.sismics.docs.core.dao.jpa.AclDao;
import com.sismics.docs.core.dao.jpa.RouteDao;
import com.sismics.docs.core.dao.jpa.RouteModelDao;
import com.sismics.docs.core.dao.jpa.RouteStepDao;
import com.sismics.docs.core.dao.jpa.dto.RouteStepDto;
import com.sismics.docs.core.model.jpa.Route;
import com.sismics.docs.core.model.jpa.RouteModel;
import com.sismics.docs.core.model.jpa.RouteStep;
@@ -14,6 +16,7 @@ import com.sismics.docs.core.util.RoutingUtil;
import com.sismics.docs.core.util.SecurityUtil;
import com.sismics.rest.exception.ClientException;
import com.sismics.rest.exception.ForbiddenClientException;
import com.sismics.rest.util.ValidationUtil;
import javax.json.*;
import javax.ws.rs.FormParam;
@@ -79,9 +82,8 @@ public class RouteResource extends BaseResource {
RouteStepDao routeStepDao = new RouteStepDao();
try (JsonReader reader = Json.createReader(new StringReader(routeModel.getSteps()))) {
JsonArray stepsJson = reader.readArray();
int order = 0;
for (int i = 0; i < stepsJson.size(); i++) {
JsonObject step = stepsJson.getJsonObject(i);
for (int order = 0; order < stepsJson.size(); order++) {
JsonObject step = stepsJson.getJsonObject(order);
JsonObject target = step.getJsonObject("target");
AclTargetType targetType = AclTargetType.valueOf(target.getString("type"));
String targetName = target.getString("name");
@@ -89,7 +91,7 @@ public class RouteResource extends BaseResource {
RouteStep routeStep = new RouteStep()
.setRouteId(route.getId())
.setName(step.getString("name"))
.setOrder(order++)
.setOrder(order)
.setType(RouteStepType.valueOf(step.getString("type")))
.setTargetId(SecurityUtil.getTargetIdFromName(targetName, targetType));
@@ -98,18 +100,82 @@ public class RouteResource extends BaseResource {
}
routeStepDao.create(routeStep);
if (i == 0) {
// Initialize ACL on the first step
RoutingUtil.updateAcl(documentId, routeStep, null, principal.getId());
// TODO Send an email to the targetId users
}
}
}
// Intialize ACLs on the first step
RouteStepDto routeStep = routeStepDao.getCurrentStep(documentId);
RoutingUtil.updateAcl(documentId, routeStep, null, principal.getId());
// Always return OK
JsonObjectBuilder response = Json.createObjectBuilder()
.add("status", "ok");
return Response.ok().entity(response.build()).build();
}
/**
* Validate the current step of a route.
*
* @api {post} /route/validate Validate the current step of a route
* @apiName PostRouteValidate
* @apiRouteModel Route
* @apiParam {String} documentId Document ID
* @apiParam {String} transition Route step transition
* @apiParam {String} comment Route step comment
* @apiSuccess {String} status Status OK
* @apiError (client) ForbiddenError Access denied
* @apiError (client) NotFound Document or route not found
* @apiPermission user
* @apiVersion 1.5.0
*
* @return Response
*/
@POST
@Path("validate")
public Response validate(@FormParam("documentId") String documentId,
@FormParam("transition") String transitionStr,
@FormParam("comment") String comment) {
if (!authenticate()) {
throw new ForbiddenClientException();
}
// Get the document
AclDao aclDao = new AclDao();
if (!aclDao.checkPermission(documentId, PermType.READ, getTargetIdList(null))) {
throw new NotFoundException();
}
// Get the current step
RouteStepDao routeStepDao = new RouteStepDao();
RouteStepDto routeStep = routeStepDao.getCurrentStep(documentId);
if (routeStep == null) {
throw new NotFoundException();
}
// Check permission to validate this step
if (!getTargetIdList(null).contains(routeStep.getTargetId())) {
throw new ForbiddenClientException();
}
// Validate data
ValidationUtil.validateRequired(transitionStr, "transition");
comment = ValidationUtil.validateLength(comment, "comment", 1, 500, true);
RouteStepTransition transition = RouteStepTransition.valueOf(transitionStr);
if (routeStep.getType() == RouteStepType.VALIDATE && transition != RouteStepTransition.VALIDATED
|| routeStep.getType() == RouteStepType.APPROVE && transition != RouteStepTransition.APPROVED && transition != RouteStepTransition.REJECTED) {
throw new ClientException("ValidationError", "Invalid transition for this route step type");
}
// Validate the step and update ACLs
routeStepDao.endRouteStep(routeStep.getId(), transition, comment, principal.getId());
RouteStepDto newRouteStep = routeStepDao.getCurrentStep(documentId);
RoutingUtil.updateAcl(documentId, newRouteStep, routeStep, principal.getId());
// TODO Send an email to the new route step
// Always return OK
// TODO Return if the document is still readable and return the new current step if any
JsonObjectBuilder response = Json.createObjectBuilder()
.add("status", "ok");
return Response.ok().entity(response.build()).build();
}
}

View File

@@ -2,7 +2,6 @@ package com.sismics.docs.rest.resource;
import com.sismics.docs.core.constant.AclTargetType;
import com.sismics.docs.core.constant.AclType;
import com.sismics.docs.core.constant.PermType;
import com.sismics.docs.core.dao.jpa.AclDao;
import com.sismics.docs.core.dao.jpa.ShareDao;
@@ -77,7 +76,6 @@ public class ShareResource extends BaseResource {
Acl acl = new Acl();
acl.setSourceId(documentId);
acl.setPerm(PermType.READ);
acl.setType(AclType.USER);
acl.setTargetId(share.getId());
aclDao.create(acl, principal.getId());
@@ -121,7 +119,7 @@ public class ShareResource extends BaseResource {
if (aclList.isEmpty()) {
throw new ClientException("ShareNotFound", MessageFormat.format("Share not found: {0}", id));
}
Acl acl = aclList.get(0);
if (!aclDao.checkPermission(acl.getSourceId(), PermType.WRITE, getTargetIdList(null))) {
throw new ClientException("DocumentNotFound", MessageFormat.format("Document not found: {0}", acl.getSourceId()));

View File

@@ -8,6 +8,7 @@ import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.Response;
import java.util.Date;
@@ -64,6 +65,7 @@ public class TestRouteResource extends BaseJerseyTest {
JsonObject routeStep = json.getJsonObject("route_step");
Assert.assertNotNull(routeStep);
Assert.assertFalse(routeStep.getBoolean("transitionable"));
Assert.assertEquals("Check the document's metadata", routeStep.getString("name"));
// Get document 1 as admin
json = target().path("/document/" + document1Id).request()
@@ -72,5 +74,56 @@ public class TestRouteResource extends BaseJerseyTest {
routeStep = json.getJsonObject("route_step");
Assert.assertNotNull(routeStep);
Assert.assertTrue(routeStep.getBoolean("transitionable"));
Assert.assertEquals("Check the document's metadata", routeStep.getString("name"));
// Validate the current step with admin
target().path("/route/validate").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.post(Entity.form(new Form()
.param("documentId", document1Id)
.param("transition", "VALIDATED")), JsonObject.class);
// Get document 1 as admin
json = target().path("/document/" + document1Id).request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.get(JsonObject.class);
routeStep = json.getJsonObject("route_step");
Assert.assertNotNull(routeStep);
Assert.assertEquals("Add relevant files to the document", routeStep.getString("name"));
// Validate the current step with admin
target().path("/route/validate").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.post(Entity.form(new Form()
.param("documentId", document1Id)
.param("transition", "VALIDATED")
.param("comment", "OK")), JsonObject.class);
// Get document 1 as admin
json = target().path("/document/" + document1Id).request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.get(JsonObject.class);
routeStep = json.getJsonObject("route_step");
Assert.assertNotNull(routeStep);
Assert.assertEquals("Approve the document", routeStep.getString("name"));
// Validate the current step with admin
target().path("/route/validate").request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.post(Entity.form(new Form()
.param("documentId", document1Id)
.param("transition", "APPROVED")), JsonObject.class);
// Get document 1 as admin
Response response = target().path("/document/" + document1Id).request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
.get();
Assert.assertEquals(Response.Status.NOT_FOUND, Response.Status.fromStatusCode(response.getStatus()));
// Get document 1 as admin
json = target().path("/document/" + document1Id).request()
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, route1Token)
.get(JsonObject.class);
Assert.assertFalse(json.containsKey("route_step"));
}
}