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:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user