mirror of
https://github.com/sismics/docs.git
synced 2024-06-02 08:34:32 +02:00
398 lines
15 KiB
Java
398 lines
15 KiB
Java
package com.sismics.docs.rest.resource;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.sismics.docs.core.constant.*;
|
|
import com.sismics.docs.core.dao.AclDao;
|
|
import com.sismics.docs.core.dao.GroupDao;
|
|
import com.sismics.docs.core.dao.RouteModelDao;
|
|
import com.sismics.docs.core.dao.UserDao;
|
|
import com.sismics.docs.core.dao.criteria.RouteModelCriteria;
|
|
import com.sismics.docs.core.dao.dto.RouteModelDto;
|
|
import com.sismics.docs.core.model.jpa.Acl;
|
|
import com.sismics.docs.core.model.jpa.Group;
|
|
import com.sismics.docs.core.model.jpa.RouteModel;
|
|
import com.sismics.docs.core.model.jpa.User;
|
|
import com.sismics.docs.core.util.ActionUtil;
|
|
import com.sismics.docs.core.util.jpa.SortCriteria;
|
|
import com.sismics.docs.rest.constant.BaseFunction;
|
|
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 javax.json.*;
|
|
import javax.ws.rs.*;
|
|
import javax.ws.rs.core.Response;
|
|
import java.io.StringReader;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Route model REST resources.
|
|
*
|
|
* @author bgamard
|
|
*/
|
|
@Path("/routemodel")
|
|
public class RouteModelResource extends BaseResource {
|
|
/**
|
|
* Returns the list of all route models.
|
|
*
|
|
* @api {get} /routemodel Get route models
|
|
* @apiName GetRouteModel
|
|
* @apiGroup RouteModel
|
|
* @apiParam {Number} sort_column Column index to sort on
|
|
* @apiParam {Boolean} asc If true, sort in ascending order
|
|
* @apiSuccess {Object[]} routemodels List of route models
|
|
* @apiSuccess {String} routemodels.id ID
|
|
* @apiSuccess {String} routemodels.name Name
|
|
* @apiSuccess {Number} routemodels.create_date Create date (timestamp)
|
|
* @apiError (client) ForbiddenError Access denied
|
|
* @apiPermission user
|
|
* @apiVersion 1.5.0
|
|
*
|
|
* @return Response
|
|
*/
|
|
@GET
|
|
public Response list(
|
|
@QueryParam("sort_column") Integer sortColumn,
|
|
@QueryParam("asc") Boolean asc) {
|
|
if (!authenticate()) {
|
|
throw new ForbiddenClientException();
|
|
}
|
|
|
|
JsonArrayBuilder routeModels = Json.createArrayBuilder();
|
|
SortCriteria sortCriteria = new SortCriteria(sortColumn, asc);
|
|
|
|
RouteModelDao routeModelDao = new RouteModelDao();
|
|
List<RouteModelDto> routeModelDtoList = routeModelDao.findByCriteria(new RouteModelCriteria().setTargetIdList(getTargetIdList(null)), sortCriteria);
|
|
for (RouteModelDto routeModelDto : routeModelDtoList) {
|
|
routeModels.add(Json.createObjectBuilder()
|
|
.add("id", routeModelDto.getId())
|
|
.add("name", routeModelDto.getName())
|
|
.add("create_date", routeModelDto.getCreateTimestamp()));
|
|
}
|
|
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
.add("routemodels", routeModels);
|
|
return Response.ok().entity(response.build()).build();
|
|
}
|
|
|
|
/**
|
|
* Add a route model.
|
|
*
|
|
* @api {put} /routemodel Add a route model
|
|
* @apiName PutRouteModel
|
|
* @apiGroup RouteModel
|
|
* @apiParam {String} name Route model name
|
|
* @apiParam {String} steps Steps data in JSON
|
|
* @apiSuccess {String} id Route model ID
|
|
* @apiError (client) ForbiddenError Access denied
|
|
* @apiError (client) ValidationError Validation error
|
|
* @apiPermission admin
|
|
* @apiVersion 1.5.0
|
|
*
|
|
* @return Response
|
|
*/
|
|
@PUT
|
|
public Response add(@FormParam("name") String name, @FormParam("steps") String steps) {
|
|
if (!authenticate()) {
|
|
throw new ForbiddenClientException();
|
|
}
|
|
checkBaseFunction(BaseFunction.ADMIN);
|
|
|
|
// Validate input
|
|
name = ValidationUtil.validateLength(name, "name", 1, 50, false);
|
|
steps = ValidationUtil.validateLength(steps, "steps", 1, 5000, false);
|
|
validateRouteModelSteps(steps);
|
|
|
|
// Create the route model
|
|
RouteModelDao routeModelDao = new RouteModelDao();
|
|
String id = routeModelDao.create(new RouteModel()
|
|
.setName(name)
|
|
.setSteps(steps), principal.getId());
|
|
|
|
// Create read ACL
|
|
AclDao aclDao = new AclDao();
|
|
Acl acl = new Acl();
|
|
acl.setPerm(PermType.READ);
|
|
acl.setType(AclType.USER);
|
|
acl.setSourceId(id);
|
|
acl.setTargetId(principal.getId());
|
|
aclDao.create(acl, principal.getId());
|
|
|
|
// Create write ACL
|
|
acl = new Acl();
|
|
acl.setPerm(PermType.WRITE);
|
|
acl.setType(AclType.USER);
|
|
acl.setSourceId(id);
|
|
acl.setTargetId(principal.getId());
|
|
aclDao.create(acl, principal.getId());
|
|
|
|
// Always return OK
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
.add("id", id);
|
|
return Response.ok().entity(response.build()).build();
|
|
}
|
|
|
|
/**
|
|
* Validate route model steps.
|
|
*
|
|
* @param steps Route model steps data
|
|
*/
|
|
private void validateRouteModelSteps(String steps) {
|
|
UserDao userDao = new UserDao();
|
|
GroupDao groupDao = new GroupDao();
|
|
|
|
try (JsonReader reader = Json.createReader(new StringReader(steps))) {
|
|
JsonArray stepsJson = reader.readArray();
|
|
if (stepsJson.isEmpty()) {
|
|
throw new ClientException("ValidationError", "At least one step is required");
|
|
}
|
|
for (int i = 0; i < stepsJson.size(); i++) {
|
|
JsonObject step = stepsJson.getJsonObject(i);
|
|
if (step.size() != 4) {
|
|
throw new ClientException("ValidationError", "Steps data not valid");
|
|
}
|
|
|
|
// Name
|
|
ValidationUtil.validateLength(step.getString("name"), "step.name", 1, 200, false);
|
|
|
|
// Type
|
|
String typeStr = step.getString("type");
|
|
RouteStepType type;
|
|
try {
|
|
type = RouteStepType.valueOf(typeStr);
|
|
} catch (IllegalArgumentException e) {
|
|
throw new ClientException("ValidationError", typeStr + "is not a valid route step type");
|
|
}
|
|
|
|
// Target
|
|
JsonObject target = step.getJsonObject("target");
|
|
if (target.size() != 2) {
|
|
throw new ClientException("ValidationError", "Step target is not valid");
|
|
}
|
|
AclTargetType targetType;
|
|
String targetTypeStr = target.getString("type");
|
|
String targetName = target.getString("name");
|
|
ValidationUtil.validateRequired(targetName, "step.target.name");
|
|
ValidationUtil.validateRequired(targetTypeStr, "step.target.type");
|
|
try {
|
|
targetType = AclTargetType.valueOf(targetTypeStr);
|
|
} catch (IllegalArgumentException e) {
|
|
throw new ClientException("ValidationError", targetTypeStr + " is not a valid ACL target type");
|
|
}
|
|
switch (targetType) {
|
|
case USER:
|
|
User user = userDao.getActiveByUsername(targetName);
|
|
if (user == null) {
|
|
throw new ClientException("ValidationError", targetName + " is not a valid user");
|
|
}
|
|
break;
|
|
case GROUP:
|
|
Group group = groupDao.getActiveByName(targetName);
|
|
if (group == null) {
|
|
throw new ClientException("ValidationError", targetName + " is not a valid group");
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Transitions
|
|
List<RouteStepTransition> transitionsNames = Lists.newArrayList();
|
|
JsonArray transitions = step.getJsonArray("transitions");
|
|
if (type == RouteStepType.VALIDATE) {
|
|
if (transitions.size() != 1) {
|
|
throw new ClientException("ValidationError", "VALIDATE steps should have one transition");
|
|
}
|
|
transitionsNames.add(RouteStepTransition.VALIDATED);
|
|
} else if (type == RouteStepType.APPROVE) {
|
|
if (transitions.size() != 2) {
|
|
throw new ClientException("ValidationError", "APPROVE steps should have two transition");
|
|
}
|
|
transitionsNames.add(RouteStepTransition.APPROVED);
|
|
transitionsNames.add(RouteStepTransition.REJECTED);
|
|
}
|
|
|
|
for (int j = 0; j < transitions.size(); j++) {
|
|
// Transition
|
|
JsonObject transition = transitions.getJsonObject(j);
|
|
if (transition.size() != 2) {
|
|
throw new ClientException("ValidationError", "Transition data is not valid");
|
|
}
|
|
|
|
// Transition name
|
|
String routeStepTransitionStr = transition.getString("name");
|
|
ValidationUtil.validateRequired(routeStepTransitionStr, "step.transitions.name");
|
|
RouteStepTransition routeStepTransition;
|
|
try {
|
|
routeStepTransition = RouteStepTransition.valueOf(routeStepTransitionStr);
|
|
} catch (IllegalArgumentException e) {
|
|
throw new ClientException("ValidationError", routeStepTransitionStr + " is not a valid route step transition type");
|
|
}
|
|
if (!transitionsNames.contains(routeStepTransition)) {
|
|
throw new ClientException("ValidationError", routeStepTransitionStr + " is not allowed for this step type");
|
|
}
|
|
|
|
// Actions
|
|
JsonArray actions = transition.getJsonArray("actions");
|
|
for (int k = 0; k < actions.size(); k++) {
|
|
JsonObject action = actions.getJsonObject(k);
|
|
|
|
// Action type
|
|
String actionTypeStr = action.getString("type");
|
|
ActionType actionType;
|
|
ValidationUtil.validateRequired(routeStepTransitionStr, "step.transitions.actions.type");
|
|
try {
|
|
actionType = ActionType.valueOf(actionTypeStr);
|
|
} catch (IllegalArgumentException e) {
|
|
throw new ClientException("ValidationError", actionTypeStr + " is not a valid action type");
|
|
}
|
|
|
|
// Validate action
|
|
try {
|
|
ActionUtil.validateAction(actionType, action);
|
|
} catch (Exception e) {
|
|
throw new ClientException("ValidationError", e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (JsonException e) {
|
|
throw new ClientException("ValidationError", "Steps data not valid");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a route model.
|
|
*
|
|
* @api {post} /routemodel/:id Update a route model
|
|
* @apiName PostRouteModel
|
|
* @apiGroup RouteModel
|
|
* @apiParam {String} name Route model name
|
|
* @apiParam {String} steps Steps data in JSON
|
|
* @apiSuccess {String} status Status OK
|
|
* @apiError (client) ForbiddenError Access denied
|
|
* @apiError (client) ValidationError Validation error
|
|
* @apiError (client) NotFound Route model not found
|
|
* @apiPermission admin
|
|
* @apiVersion 1.5.0
|
|
*
|
|
* @return Response
|
|
*/
|
|
@POST
|
|
@Path("{id: [a-z0-9\\-]+}")
|
|
public Response update(@PathParam("id") String id,
|
|
@FormParam("name") String name,
|
|
@FormParam("steps") String steps) {
|
|
if (!authenticate()) {
|
|
throw new ForbiddenClientException();
|
|
}
|
|
checkBaseFunction(BaseFunction.ADMIN);
|
|
|
|
// Validate input
|
|
name = ValidationUtil.validateLength(name, "name", 1, 50, false);
|
|
steps = ValidationUtil.validateLength(steps, "steps", 1, 5000, false);
|
|
validateRouteModelSteps(steps);
|
|
|
|
// Get the route model
|
|
RouteModelDao routeModelDao = new RouteModelDao();
|
|
RouteModel routeModel = routeModelDao.getActiveById(id);
|
|
if (routeModel == null) {
|
|
throw new NotFoundException();
|
|
}
|
|
|
|
// Update the route model
|
|
routeModelDao.update(routeModel.setName(name)
|
|
.setSteps(steps), principal.getId());
|
|
|
|
// Always return OK
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
.add("status", "ok");
|
|
return Response.ok().entity(response.build()).build();
|
|
}
|
|
|
|
/**
|
|
* Delete a route model.
|
|
*
|
|
* @api {delete} /routemodel/:id Delete a route model
|
|
* @apiName DeleteRouteModel
|
|
* @apiGroup RouteModel
|
|
* @apiParam {String} id Route model ID
|
|
* @apiSuccess {String} status Status OK
|
|
* @apiError (client) ForbiddenError Access denied
|
|
* @apiError (client) NotFound Route model not found
|
|
* @apiPermission admin
|
|
* @apiVersion 1.5.0
|
|
*
|
|
* @return Response
|
|
*/
|
|
@DELETE
|
|
@Path("{id: [a-z0-9\\-]+}")
|
|
public Response delete(@PathParam("id") String id) {
|
|
if (!authenticate()) {
|
|
throw new ForbiddenClientException();
|
|
}
|
|
checkBaseFunction(BaseFunction.ADMIN);
|
|
|
|
// Get the route model
|
|
RouteModelDao routeModelDao = new RouteModelDao();
|
|
RouteModel routeModel = routeModelDao.getActiveById(id);
|
|
if (routeModel == null) {
|
|
throw new NotFoundException();
|
|
}
|
|
|
|
// Delete the route model
|
|
routeModelDao.delete(routeModel.getId(), principal.getId());
|
|
|
|
// Always return OK
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
.add("status", "ok");
|
|
return Response.ok().entity(response.build()).build();
|
|
}
|
|
|
|
/**
|
|
* Get a route model.
|
|
*
|
|
* @api {get} /routemodel/:id Get a route model
|
|
* @apiName GetRouteModel
|
|
* @apiGroup RouteModel
|
|
* @apiParam {String} id Route model ID
|
|
* @apiSuccess {String} id Route model ID
|
|
* @apiSuccess {String} name Route model name
|
|
* @apiSuccess {String} create_date Create date (timestamp)
|
|
* @apiSuccess {String} steps Steps data in JSON
|
|
* @apiError (client) ForbiddenError Access denied
|
|
* @apiError (client) NotFound Route model not found
|
|
* @apiPermission admin
|
|
* @apiVersion 1.5.0
|
|
*
|
|
* @param id RouteModel name
|
|
* @return Response
|
|
*/
|
|
@GET
|
|
@Path("{id: [a-z0-9\\-]+}")
|
|
public Response get(@PathParam("id") String id) {
|
|
if (!authenticate()) {
|
|
throw new ForbiddenClientException();
|
|
}
|
|
checkBaseFunction(BaseFunction.ADMIN);
|
|
|
|
// Get the route model
|
|
RouteModelDao routeModelDao = new RouteModelDao();
|
|
RouteModel routeModel = routeModelDao.getActiveById(id);
|
|
if (routeModel == null) {
|
|
throw new NotFoundException();
|
|
}
|
|
|
|
// Build the response
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
.add("id", routeModel.getId())
|
|
.add("name", routeModel.getName())
|
|
.add("create_date", routeModel.getCreateDate().getTime())
|
|
.add("steps", routeModel.getSteps());
|
|
|
|
// Add ACL
|
|
AclUtil.addAcls(response, id, getTargetIdList(null));
|
|
|
|
return Response.ok().entity(response.build()).build();
|
|
}
|
|
}
|