mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 14:07:55 +01:00
#202 Actions on route transition
This commit is contained in:
parent
9ca27d7c12
commit
995e45d28f
@ -0,0 +1,13 @@
|
|||||||
|
package com.sismics.docs.core.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action types.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public enum ActionType {
|
||||||
|
/**
|
||||||
|
* Add a tag.
|
||||||
|
*/
|
||||||
|
ADD_TAG
|
||||||
|
}
|
@ -68,7 +68,7 @@ public class RouteStepDao {
|
|||||||
Map<String, Object> parameterMap = new HashMap<>();
|
Map<String, Object> parameterMap = new HashMap<>();
|
||||||
List<String> criteriaList = new ArrayList<>();
|
List<String> criteriaList = new ArrayList<>();
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder("select rs.RTP_ID_C, rs.RTP_NAME_C c0, rs.RTP_TYPE_C c1, rs.RTP_TRANSITION_C c2, rs.RTP_COMMENT_C c3, rs.RTP_IDTARGET_C c4, u.USE_USERNAME_C as targetUsername, g.GRP_NAME_C, rs.RTP_ENDDATE_D c5, uv.USE_USERNAME_C as validatorUsername, rs.RTP_IDROUTE_C, rs.RTP_ORDER_N c6")
|
StringBuilder sb = new StringBuilder("select rs.RTP_ID_C, rs.RTP_NAME_C c0, rs.RTP_TYPE_C c1, rs.RTP_TRANSITION_C c2, rs.RTP_COMMENT_C c3, rs.RTP_IDTARGET_C c4, u.USE_USERNAME_C as targetUsername, g.GRP_NAME_C, rs.RTP_ENDDATE_D c5, uv.USE_USERNAME_C as validatorUsername, rs.RTP_IDROUTE_C, rs.RTP_TRANSITIONS_C, rs.RTP_ORDER_N c6")
|
||||||
.append(" from T_ROUTE_STEP rs ")
|
.append(" from T_ROUTE_STEP rs ")
|
||||||
.append(" join T_ROUTE r on r.RTE_ID_C = rs.RTP_IDROUTE_C ")
|
.append(" join T_ROUTE r on r.RTE_ID_C = rs.RTP_IDROUTE_C ")
|
||||||
.append(" left join T_USER uv on uv.USE_ID_C = rs.RTP_IDVALIDATORUSER_C ")
|
.append(" left join T_USER uv on uv.USE_ID_C = rs.RTP_IDVALIDATORUSER_C ")
|
||||||
@ -124,7 +124,8 @@ public class RouteStepDao {
|
|||||||
Timestamp endDateTimestamp = (Timestamp) o[i++];
|
Timestamp endDateTimestamp = (Timestamp) o[i++];
|
||||||
dto.setEndDateTimestamp(endDateTimestamp == null ? null : endDateTimestamp.getTime());
|
dto.setEndDateTimestamp(endDateTimestamp == null ? null : endDateTimestamp.getTime());
|
||||||
dto.setValidatorUserName((String) o[i++]);
|
dto.setValidatorUserName((String) o[i++]);
|
||||||
dto.setRouteId((String) o[i]);
|
dto.setRouteId((String) o[i++]);
|
||||||
|
dto.setTransitions((String) o[i]);
|
||||||
dtoList.add(dto);
|
dtoList.add(dto);
|
||||||
}
|
}
|
||||||
return dtoList;
|
return dtoList;
|
||||||
|
@ -195,10 +195,6 @@ public class TagDao {
|
|||||||
criteriaList.add("dt.DOT_IDDOCUMENT_C = :documentId");
|
criteriaList.add("dt.DOT_IDDOCUMENT_C = :documentId");
|
||||||
parameterMap.put("documentId", criteria.getDocumentId());
|
parameterMap.put("documentId", criteria.getDocumentId());
|
||||||
}
|
}
|
||||||
if (criteria.getName() != null) {
|
|
||||||
criteriaList.add("t.TAG_NAME_C = :name");
|
|
||||||
parameterMap.put("name", criteria.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
criteriaList.add("t.TAG_DELETEDATE_D is null");
|
criteriaList.add("t.TAG_DELETEDATE_D is null");
|
||||||
|
|
||||||
|
@ -54,13 +54,4 @@ public class TagCriteria {
|
|||||||
this.documentId = documentId;
|
this.documentId = documentId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TagCriteria setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,11 @@ public class RouteStepDto {
|
|||||||
*/
|
*/
|
||||||
private String validatorUserName;
|
private String validatorUserName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transitions data.
|
||||||
|
*/
|
||||||
|
private String transitions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route ID.
|
* Route ID.
|
||||||
*/
|
*/
|
||||||
@ -166,6 +171,15 @@ public class RouteStepDto {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTransitions() {
|
||||||
|
return transitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RouteStepDto setTransitions(String transitions) {
|
||||||
|
this.transitions = transitions;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform in JSON.
|
* Transform in JSON.
|
||||||
*
|
*
|
||||||
|
@ -54,6 +54,12 @@ public class RouteStep {
|
|||||||
@Column(name = "RTP_COMMENT_C", length = 500)
|
@Column(name = "RTP_COMMENT_C", length = 500)
|
||||||
private String comment;
|
private String comment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transitions JSON data.
|
||||||
|
*/
|
||||||
|
@Column(name = "RTP_TRANSITIONS_C", length = 2000)
|
||||||
|
private String transitions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target ID (user or group).
|
* Target ID (user or group).
|
||||||
*/
|
*/
|
||||||
@ -198,6 +204,15 @@ public class RouteStep {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTransitions() {
|
||||||
|
return transitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RouteStep setTransitions(String transitions) {
|
||||||
|
this.transitions = transitions;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.sismics.docs.core.util;
|
||||||
|
|
||||||
|
import com.sismics.docs.core.constant.ActionType;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
||||||
|
import com.sismics.docs.core.util.action.Action;
|
||||||
|
import com.sismics.docs.core.util.action.AddTagAction;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action utilities.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class ActionUtil {
|
||||||
|
/**
|
||||||
|
* Logger.
|
||||||
|
*/
|
||||||
|
private static final org.slf4j.Logger log = LoggerFactory.getLogger(LuceneUtil.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute an action.
|
||||||
|
*
|
||||||
|
* @param actionType Action type
|
||||||
|
* @param actionData Action data
|
||||||
|
* @param documentDto Document DTO
|
||||||
|
*/
|
||||||
|
public static void executeAction(ActionType actionType, JsonObject actionData, DocumentDto documentDto) {
|
||||||
|
Action action;
|
||||||
|
switch (actionType) {
|
||||||
|
case ADD_TAG:
|
||||||
|
action = new AddTagAction();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log.error("Action type not handled: " + actionType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
action.execute(documentDto, actionData);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.sismics.docs.core.util.action;
|
||||||
|
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.DocumentDto;
|
||||||
|
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base action interface.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public interface Action {
|
||||||
|
/**
|
||||||
|
* Execute the action.
|
||||||
|
*
|
||||||
|
* @param documentDto Document DTO
|
||||||
|
* @param action Action data
|
||||||
|
*/
|
||||||
|
void execute(DocumentDto documentDto, JsonObject action);
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.sismics.docs.core.util.action;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
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.DocumentDto;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.TagDto;
|
||||||
|
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to add a tag.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class AddTagAction implements Action {
|
||||||
|
@Override
|
||||||
|
public void execute(DocumentDto documentDto, JsonObject action) {
|
||||||
|
if (action.getString("tag") == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TagDao tagDao = new TagDao();
|
||||||
|
List<TagDto> tagAddDtoList = tagDao.findByCriteria(new TagCriteria().setId(action.getString("tag")), null);
|
||||||
|
if (tagAddDtoList.isEmpty()) {
|
||||||
|
// The tag has been deleted since the route model creation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TagDto> tagDtoList = tagDao.findByCriteria(new TagCriteria().setDocumentId(documentDto.getId()), null);
|
||||||
|
Set<String> tagIdSet = Sets.newHashSet(tagAddDtoList.get(0).getId());
|
||||||
|
for (TagDto tagDto : tagDtoList) {
|
||||||
|
tagIdSet.add(tagDto.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
tagDao.updateTagList(documentDto.getId(), tagIdSet);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
alter table T_DOCUMENT add column DOC_UPDATEDATE_D datetime;
|
alter table T_DOCUMENT add column DOC_UPDATEDATE_D datetime;
|
||||||
update T_DOCUMENT set DOC_UPDATEDATE_D = DOC_CREATEDATE_D;
|
update T_DOCUMENT set DOC_UPDATEDATE_D = DOC_CREATEDATE_D;
|
||||||
alter table T_DOCUMENT alter column DOC_UPDATEDATE_D datetime not null;
|
alter table T_DOCUMENT alter column DOC_UPDATEDATE_D datetime not null;
|
||||||
|
alter table T_ROUTE_STEP add column RTP_TRANSITIONS_C varchar(2000);
|
||||||
update T_CONFIG set CFG_VALUE_C = '18' where CFG_ID_C = 'DB_VERSION';
|
update T_CONFIG set CFG_VALUE_C = '18' where CFG_ID_C = 'DB_VERSION';
|
||||||
|
@ -41,7 +41,7 @@ public class AuditLogResource extends BaseResource {
|
|||||||
* @apiSuccess {String} logs.id ID
|
* @apiSuccess {String} logs.id ID
|
||||||
* @apiSuccess {String} logs.username Username
|
* @apiSuccess {String} logs.username Username
|
||||||
* @apiSuccess {String} logs.target Entity ID
|
* @apiSuccess {String} logs.target Entity ID
|
||||||
* @apiSuccess {String="Acl","Comment","Document","File","Group","Tag","User","RouteModel"} logs.class Entity type
|
* @apiSuccess {String="Acl","Comment","Document","File","Group","Tag","User","RouteModel","Route"} logs.class Entity type
|
||||||
* @apiSuccess {String="CREATE","UPDATE","DELETE"} logs.type Type
|
* @apiSuccess {String="CREATE","UPDATE","DELETE"} logs.type Type
|
||||||
* @apiSuccess {String} logs.message Message
|
* @apiSuccess {String} logs.message Message
|
||||||
* @apiSuccess {Number} logs.create_date Create date (timestamp)
|
* @apiSuccess {Number} logs.create_date Create date (timestamp)
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
package com.sismics.docs.rest.resource;
|
package com.sismics.docs.rest.resource;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.sismics.docs.core.constant.AclTargetType;
|
import com.sismics.docs.core.constant.AclTargetType;
|
||||||
|
import com.sismics.docs.core.constant.ActionType;
|
||||||
|
import com.sismics.docs.core.constant.RouteStepTransition;
|
||||||
import com.sismics.docs.core.constant.RouteStepType;
|
import com.sismics.docs.core.constant.RouteStepType;
|
||||||
import com.sismics.docs.core.dao.jpa.GroupDao;
|
import com.sismics.docs.core.dao.jpa.GroupDao;
|
||||||
import com.sismics.docs.core.dao.jpa.RouteModelDao;
|
import com.sismics.docs.core.dao.jpa.RouteModelDao;
|
||||||
|
import com.sismics.docs.core.dao.jpa.TagDao;
|
||||||
import com.sismics.docs.core.dao.jpa.UserDao;
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
||||||
import com.sismics.docs.core.dao.jpa.criteria.RouteModelCriteria;
|
import com.sismics.docs.core.dao.jpa.criteria.RouteModelCriteria;
|
||||||
|
import com.sismics.docs.core.dao.jpa.criteria.TagCriteria;
|
||||||
import com.sismics.docs.core.dao.jpa.dto.RouteModelDto;
|
import com.sismics.docs.core.dao.jpa.dto.RouteModelDto;
|
||||||
|
import com.sismics.docs.core.dao.jpa.dto.TagDto;
|
||||||
import com.sismics.docs.core.model.jpa.Group;
|
import com.sismics.docs.core.model.jpa.Group;
|
||||||
import com.sismics.docs.core.model.jpa.RouteModel;
|
import com.sismics.docs.core.model.jpa.RouteModel;
|
||||||
import com.sismics.docs.core.model.jpa.User;
|
import com.sismics.docs.core.model.jpa.User;
|
||||||
@ -120,6 +126,7 @@ public class RouteModelResource extends BaseResource {
|
|||||||
private void validateRouteModelSteps(String steps) {
|
private void validateRouteModelSteps(String steps) {
|
||||||
UserDao userDao = new UserDao();
|
UserDao userDao = new UserDao();
|
||||||
GroupDao groupDao = new GroupDao();
|
GroupDao groupDao = new GroupDao();
|
||||||
|
TagDao tagDao = new TagDao();
|
||||||
|
|
||||||
try (JsonReader reader = Json.createReader(new StringReader(steps))) {
|
try (JsonReader reader = Json.createReader(new StringReader(steps))) {
|
||||||
JsonArray stepsJson = reader.readArray();
|
JsonArray stepsJson = reader.readArray();
|
||||||
@ -128,19 +135,26 @@ public class RouteModelResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < stepsJson.size(); i++) {
|
for (int i = 0; i < stepsJson.size(); i++) {
|
||||||
JsonObject step = stepsJson.getJsonObject(i);
|
JsonObject step = stepsJson.getJsonObject(i);
|
||||||
if (step.size() != 3) {
|
if (step.size() != 4) {
|
||||||
throw new ClientException("ValidationError", "Steps data not valid");
|
throw new ClientException("ValidationError", "Steps data not valid");
|
||||||
}
|
}
|
||||||
String type = step.getString("type");
|
|
||||||
|
// Name
|
||||||
ValidationUtil.validateLength(step.getString("name"), "step.name", 1, 200, false);
|
ValidationUtil.validateLength(step.getString("name"), "step.name", 1, 200, false);
|
||||||
|
|
||||||
|
// Type
|
||||||
|
String typeStr = step.getString("type");
|
||||||
|
RouteStepType type;
|
||||||
try {
|
try {
|
||||||
RouteStepType.valueOf(type);
|
type = RouteStepType.valueOf(typeStr);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new ClientException("ValidationError", type + "is not a valid route step type");
|
throw new ClientException("ValidationError", typeStr + "is not a valid route step type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Target
|
||||||
JsonObject target = step.getJsonObject("target");
|
JsonObject target = step.getJsonObject("target");
|
||||||
if (target.size() != 2) {
|
if (target.size() != 2) {
|
||||||
throw new ClientException("ValidationError", "Steps data not valid");
|
throw new ClientException("ValidationError", "Step target is not valid");
|
||||||
}
|
}
|
||||||
AclTargetType targetType;
|
AclTargetType targetType;
|
||||||
String targetTypeStr = target.getString("type");
|
String targetTypeStr = target.getString("type");
|
||||||
@ -166,6 +180,69 @@ public class RouteModelResource extends BaseResource {
|
|||||||
}
|
}
|
||||||
break;
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Action custom fields
|
||||||
|
if (actionType == ActionType.ADD_TAG) {
|
||||||
|
String tagId = action.getString("tag");
|
||||||
|
ValidationUtil.validateRequired(routeStepTransitionStr, "step.transitions.actions.tag");
|
||||||
|
List<TagDto> tagDtoList = tagDao.findByCriteria(new TagCriteria().setId(tagId), null);
|
||||||
|
if (tagDtoList.size() != 1) {
|
||||||
|
throw new ClientException("ValidationError", tagId + " is not a valid tag");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (JsonException e) {
|
} catch (JsonException e) {
|
||||||
throw new ClientException("ValidationError", "Steps data not valid");
|
throw new ClientException("ValidationError", "Steps data not valid");
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package com.sismics.docs.rest.resource;
|
package com.sismics.docs.rest.resource;
|
||||||
|
|
||||||
import com.sismics.docs.core.constant.AclTargetType;
|
import com.sismics.docs.core.constant.*;
|
||||||
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.*;
|
import com.sismics.docs.core.dao.jpa.*;
|
||||||
import com.sismics.docs.core.dao.jpa.criteria.RouteCriteria;
|
import com.sismics.docs.core.dao.jpa.criteria.RouteCriteria;
|
||||||
import com.sismics.docs.core.dao.jpa.criteria.RouteStepCriteria;
|
import com.sismics.docs.core.dao.jpa.criteria.RouteStepCriteria;
|
||||||
@ -13,6 +10,7 @@ import com.sismics.docs.core.dao.jpa.dto.RouteStepDto;
|
|||||||
import com.sismics.docs.core.model.jpa.Route;
|
import com.sismics.docs.core.model.jpa.Route;
|
||||||
import com.sismics.docs.core.model.jpa.RouteModel;
|
import com.sismics.docs.core.model.jpa.RouteModel;
|
||||||
import com.sismics.docs.core.model.jpa.RouteStep;
|
import com.sismics.docs.core.model.jpa.RouteStep;
|
||||||
|
import com.sismics.docs.core.util.ActionUtil;
|
||||||
import com.sismics.docs.core.util.RoutingUtil;
|
import com.sismics.docs.core.util.RoutingUtil;
|
||||||
import com.sismics.docs.core.util.SecurityUtil;
|
import com.sismics.docs.core.util.SecurityUtil;
|
||||||
import com.sismics.docs.core.util.jpa.SortCriteria;
|
import com.sismics.docs.core.util.jpa.SortCriteria;
|
||||||
@ -93,12 +91,17 @@ public class RouteResource extends BaseResource {
|
|||||||
JsonObject target = step.getJsonObject("target");
|
JsonObject target = step.getJsonObject("target");
|
||||||
AclTargetType targetType = AclTargetType.valueOf(target.getString("type"));
|
AclTargetType targetType = AclTargetType.valueOf(target.getString("type"));
|
||||||
String targetName = target.getString("name");
|
String targetName = target.getString("name");
|
||||||
|
String transitions = null;
|
||||||
|
if (step.containsKey("transitions")) {
|
||||||
|
transitions = step.getJsonArray("transitions").toString();
|
||||||
|
}
|
||||||
|
|
||||||
RouteStep routeStep = new RouteStep()
|
RouteStep routeStep = new RouteStep()
|
||||||
.setRouteId(route.getId())
|
.setRouteId(route.getId())
|
||||||
.setName(step.getString("name"))
|
.setName(step.getString("name"))
|
||||||
.setOrder(order)
|
.setOrder(order)
|
||||||
.setType(RouteStepType.valueOf(step.getString("type")))
|
.setType(RouteStepType.valueOf(step.getString("type")))
|
||||||
|
.setTransitions(transitions)
|
||||||
.setTargetId(SecurityUtil.getTargetIdFromName(targetName, targetType));
|
.setTargetId(SecurityUtil.getTargetIdFromName(targetName, targetType));
|
||||||
|
|
||||||
if (routeStep.getTargetId() == null) {
|
if (routeStep.getTargetId() == null) {
|
||||||
@ -149,7 +152,9 @@ public class RouteResource extends BaseResource {
|
|||||||
|
|
||||||
// Get the document
|
// Get the document
|
||||||
AclDao aclDao = new AclDao();
|
AclDao aclDao = new AclDao();
|
||||||
if (!aclDao.checkPermission(documentId, PermType.READ, getTargetIdList(null))) {
|
DocumentDao documentDao = new DocumentDao();
|
||||||
|
DocumentDto documentDto = documentDao.getDocument(documentId, PermType.READ, getTargetIdList(null));
|
||||||
|
if (documentDto == null) {
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,18 +173,39 @@ public class RouteResource extends BaseResource {
|
|||||||
// Validate data
|
// Validate data
|
||||||
ValidationUtil.validateRequired(transitionStr, "transition");
|
ValidationUtil.validateRequired(transitionStr, "transition");
|
||||||
comment = ValidationUtil.validateLength(comment, "comment", 1, 500, true);
|
comment = ValidationUtil.validateLength(comment, "comment", 1, 500, true);
|
||||||
RouteStepTransition transition = RouteStepTransition.valueOf(transitionStr);
|
RouteStepTransition routeStepTransition = RouteStepTransition.valueOf(transitionStr);
|
||||||
if (routeStepDto.getType() == RouteStepType.VALIDATE && transition != RouteStepTransition.VALIDATED
|
if (routeStepDto.getType() == RouteStepType.VALIDATE && routeStepTransition != RouteStepTransition.VALIDATED
|
||||||
|| routeStepDto.getType() == RouteStepType.APPROVE && transition != RouteStepTransition.APPROVED && transition != RouteStepTransition.REJECTED) {
|
|| routeStepDto.getType() == RouteStepType.APPROVE
|
||||||
|
&& routeStepTransition != RouteStepTransition.APPROVED && routeStepTransition != RouteStepTransition.REJECTED) {
|
||||||
throw new ClientException("ValidationError", "Invalid transition for this route step type");
|
throw new ClientException("ValidationError", "Invalid transition for this route step type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the step and update ACLs
|
// Validate the step and update ACLs
|
||||||
routeStepDao.endRouteStep(routeStepDto.getId(), transition, comment, principal.getId());
|
routeStepDao.endRouteStep(routeStepDto.getId(), routeStepTransition, comment, principal.getId());
|
||||||
RouteStepDto newRouteStep = routeStepDao.getCurrentStep(documentId);
|
RouteStepDto newRouteStep = routeStepDao.getCurrentStep(documentId);
|
||||||
RoutingUtil.updateAcl(documentId, newRouteStep, routeStepDto, principal.getId());
|
RoutingUtil.updateAcl(documentId, newRouteStep, routeStepDto, principal.getId());
|
||||||
RoutingUtil.sendRouteStepEmail(documentId, routeStepDto);
|
RoutingUtil.sendRouteStepEmail(documentId, routeStepDto);
|
||||||
|
|
||||||
|
// Execute actions
|
||||||
|
if (routeStepDto.getTransitions() != null) {
|
||||||
|
try (JsonReader reader = Json.createReader(new StringReader(routeStepDto.getTransitions()))) {
|
||||||
|
JsonArray transitions = reader.readArray();
|
||||||
|
// Filter out our transition
|
||||||
|
for (int i = 0; i < transitions.size(); i++) {
|
||||||
|
JsonObject transition = transitions.getJsonObject(i);
|
||||||
|
if (transition.getString("name").equals(routeStepTransition.name())) {
|
||||||
|
// Transition found, execute those actions
|
||||||
|
JsonArray actions = transition.getJsonArray("actions");
|
||||||
|
for (int j = 0; j < actions.size(); j++) {
|
||||||
|
JsonObject action = actions.getJsonObject(j);
|
||||||
|
ActionType actionType = ActionType.valueOf(action.getString("type"));
|
||||||
|
ActionUtil.executeAction(actionType, action, documentDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonObjectBuilder response = Json.createObjectBuilder()
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
||||||
.add("readable", aclDao.checkPermission(documentId, PermType.READ, getTargetIdList(null)));
|
.add("readable", aclDao.checkPermission(documentId, PermType.READ, getTargetIdList(null)));
|
||||||
if (newRouteStep != null) {
|
if (newRouteStep != null) {
|
||||||
|
@ -45,9 +45,11 @@ angular.module('docs').controller('SettingsWorkflowEdit', function($scope, $dial
|
|||||||
* Add a workflow step.
|
* Add a workflow step.
|
||||||
*/
|
*/
|
||||||
$scope.addStep = function () {
|
$scope.addStep = function () {
|
||||||
$scope.workflow.steps.push({
|
var step = {
|
||||||
type: 'VALIDATE'
|
type: 'VALIDATE'
|
||||||
});
|
};
|
||||||
|
$scope.updateTransitions(step);
|
||||||
|
$scope.workflow.steps.push(step);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,6 +66,12 @@ angular.module('docs').controller('SettingsWorkflowEdit', function($scope, $dial
|
|||||||
Restangular.one('routemodel', $stateParams.id).get().then(function (data) {
|
Restangular.one('routemodel', $stateParams.id).get().then(function (data) {
|
||||||
$scope.workflow = data;
|
$scope.workflow = data;
|
||||||
$scope.workflow.steps = JSON.parse(data.steps);
|
$scope.workflow.steps = JSON.parse(data.steps);
|
||||||
|
_.each($scope.workflow.steps, function (step) {
|
||||||
|
if (!step.transitions) {
|
||||||
|
// Patch for old route models
|
||||||
|
$scope.updateTransitions(step);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$scope.workflow = {
|
$scope.workflow = {
|
||||||
@ -124,4 +132,35 @@ angular.module('docs').controller('SettingsWorkflowEdit', function($scope, $dial
|
|||||||
$scope.removeStep = function (step) {
|
$scope.removeStep = function (step) {
|
||||||
$scope.workflow.steps.splice($scope.workflow.steps.indexOf(step), 1);
|
$scope.workflow.steps.splice($scope.workflow.steps.indexOf(step), 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.updateTransitions = function (step) {
|
||||||
|
if (step.type === 'VALIDATE') {
|
||||||
|
step.transitions = [{
|
||||||
|
name: 'VALIDATED',
|
||||||
|
actions: []
|
||||||
|
}];
|
||||||
|
} else if (step.type === 'APPROVE') {
|
||||||
|
step.transitions = [{
|
||||||
|
name: 'APPROVED',
|
||||||
|
actions: []
|
||||||
|
}, {
|
||||||
|
name: 'REJECTED',
|
||||||
|
actions: []
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.addAction = function (transition) {
|
||||||
|
transition.actions.push({
|
||||||
|
type: 'ADD_TAG'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.removeAction = function (actions, action) {
|
||||||
|
actions.splice(actions.indexOf(action), 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
Restangular.one('tag/list').get().then(function(data) {
|
||||||
|
$scope.tags = data.tags;
|
||||||
|
});
|
||||||
});
|
});
|
@ -301,7 +301,9 @@
|
|||||||
"type_validate": "Validate",
|
"type_validate": "Validate",
|
||||||
"target": "Assigned to",
|
"target": "Assigned to",
|
||||||
"target_help": "<strong>Approve:</strong> Accept or reject the review<br/><strong>Validate:</strong> Review and continue the workflow",
|
"target_help": "<strong>Approve:</strong> Accept or reject the review<br/><strong>Validate:</strong> Review and continue the workflow",
|
||||||
"add_step": "Add a workflow step"
|
"add_step": "Add a workflow step",
|
||||||
|
"actions": "What happens after?",
|
||||||
|
"remove_action": "Remove action"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"security": {
|
"security": {
|
||||||
@ -507,6 +509,9 @@
|
|||||||
"number": "Number required",
|
"number": "Number required",
|
||||||
"no_space": "Spaces are not allowed"
|
"no_space": "Spaces are not allowed"
|
||||||
},
|
},
|
||||||
|
"action_type": {
|
||||||
|
"ADD_TAG": "Add this tag"
|
||||||
|
},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"previous": "Previous",
|
"previous": "Previous",
|
||||||
"next": "Next",
|
"next": "Next",
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
<span class="fas fa-exchange-alt" ng-if="step.type == 'APPROVE'"></span>
|
<span class="fas fa-exchange-alt" ng-if="step.type == 'APPROVE'"></span>
|
||||||
<span class="fas fa-check-circle" ng-if="step.type == 'VALIDATE'"></span>
|
<span class="fas fa-check-circle" ng-if="step.type == 'VALIDATE'"></span>
|
||||||
</span>
|
</span>
|
||||||
<select class="form-control" name="type-{{ $index }}" ng-model="step.type" required>
|
<select class="form-control" name="type-{{ $index }}" ng-model="step.type" ng-change="updateTransitions(step)" required>
|
||||||
<option value="APPROVE">{{ 'settings.workflow.edit.type_approve' | translate }}</option>
|
<option value="APPROVE">{{ 'settings.workflow.edit.type_approve' | translate }}</option>
|
||||||
<option value="VALIDATE">{{ 'settings.workflow.edit.type_validate' | translate }}</option>
|
<option value="VALIDATE">{{ 'settings.workflow.edit.type_validate' | translate }}</option>
|
||||||
</select>
|
</select>
|
||||||
@ -82,17 +82,54 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mt-10">
|
||||||
|
<div class="col-xs-2 text-center">
|
||||||
|
<strong>{{ 'settings.workflow.edit.actions' | translate }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-5" ng-repeat="transition in step.transitions">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading text-center">
|
||||||
|
<strong>{{ 'workflow_transition.' + transition.name | translate }}</strong>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div ng-repeat="action in transition.actions" class="mb-10 workflow-action">
|
||||||
|
<p><strong>{{ 'action_type.' + action.type | translate }}</strong></p>
|
||||||
|
<div ng-switch="action.type" class="mb-10">
|
||||||
|
<div ng-switch-when="ADD_TAG">
|
||||||
|
<select title="{{ 'action_type.ADD_TAG' | translate }}" ng-model="action.tag" required class="form-control">
|
||||||
|
<option ng-repeat="tag in tags" value="{{ tag.id }}">{{ tag.name }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-center">
|
||||||
|
<a href ng-click="removeAction(transition.actions, action)">
|
||||||
|
<span class="fas fa-minus-circle"></span> {{ 'settings.workflow.edit.remove_action' | translate }}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<select title="Action type" class="form-control">
|
||||||
|
<option name="ADD_TAG">{{ 'action_type.ADD_TAG' | translate }}</option>
|
||||||
|
</select>
|
||||||
|
<span class="input-group-addon btn" ng-click="addAction(transition)">
|
||||||
|
<span class="fas fa-plus-circle"></span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="clearfix form-group mt-10">
|
||||||
<div class="col-sm-offset-2 col-sm-10 btn-link pointer" ng-click="addStep()">
|
<div class="col-sm-offset-2 col-sm-10 btn-link pointer" ng-click="addStep()">
|
||||||
<span class="fas fa-plus-circle"></span> {{ 'settings.workflow.edit.add_step' | translate }}
|
<span class="fas fa-plus-circle"></span> {{ 'settings.workflow.edit.add_step' | translate }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="clearfix form-group mt-10">
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
<button type="submit" class="btn btn-primary" ng-click="edit()" ng-disabled="!editWorkflowForm.$valid">
|
<button type="submit" class="btn btn-primary" ng-click="edit()" ng-disabled="!editWorkflowForm.$valid">
|
||||||
<span class="fas fa-pencil-alt"></span> {{ isEdit() ? 'save' : 'add' | translate }}
|
<span class="fas fa-pencil-alt"></span> {{ isEdit() ? 'save' : 'add' | translate }}
|
||||||
|
@ -366,6 +366,11 @@ input[readonly].share-link {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workflow-action {
|
||||||
|
border: 2px dashed #ccc;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
.settings-menu {
|
.settings-menu {
|
||||||
.panel-default {
|
.panel-default {
|
||||||
|
@ -12,7 +12,7 @@ import javax.ws.rs.core.Form;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the route model resource.
|
* Test the route model resource.
|
||||||
*
|
*
|
||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
public class TestRouteModelResource extends BaseJerseyTest {
|
public class TestRouteModelResource extends BaseJerseyTest {
|
||||||
@ -23,9 +23,17 @@ public class TestRouteModelResource extends BaseJerseyTest {
|
|||||||
public void testRouteModelResource() {
|
public void testRouteModelResource() {
|
||||||
// Login admin
|
// Login admin
|
||||||
String adminToken = clientUtil.login("admin", "admin", false);
|
String adminToken = clientUtil.login("admin", "admin", false);
|
||||||
|
|
||||||
|
// Create a tag
|
||||||
|
JsonObject json = target().path("/tag").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("name", "TagRoute")
|
||||||
|
.param("color", "#ff0000")), JsonObject.class);
|
||||||
|
String tagRouteId = json.getString("id");
|
||||||
|
|
||||||
// Get all route models
|
// Get all route models
|
||||||
JsonObject json = target().path("/routemodel")
|
json = target().path("/routemodel")
|
||||||
.queryParam("sort_column", "2")
|
.queryParam("sort_column", "2")
|
||||||
.queryParam("asc", "false")
|
.queryParam("asc", "false")
|
||||||
.request()
|
.request()
|
||||||
@ -34,12 +42,12 @@ public class TestRouteModelResource extends BaseJerseyTest {
|
|||||||
JsonArray routeModels = json.getJsonArray("routemodels");
|
JsonArray routeModels = json.getJsonArray("routemodels");
|
||||||
Assert.assertEquals(1, routeModels.size());
|
Assert.assertEquals(1, routeModels.size());
|
||||||
|
|
||||||
// Create a route model
|
// Create a route model without actions
|
||||||
json = target().path("/routemodel").request()
|
json = target().path("/routemodel").request()
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
.put(Entity.form(new Form()
|
.put(Entity.form(new Form()
|
||||||
.param("name", "Workflow validation 1")
|
.param("name", "Workflow validation 1")
|
||||||
.param("steps", "[{\"type\":\"VALIDATE\",\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]")), JsonObject.class);
|
.param("steps", "[{\"type\":\"VALIDATE\",\"transitions\":[{\"name\":\"VALIDATED\",\"actions\":[]}],\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]")), JsonObject.class);
|
||||||
String routeModelId = json.getString("id");
|
String routeModelId = json.getString("id");
|
||||||
|
|
||||||
// Get all route models
|
// Get all route models
|
||||||
@ -61,14 +69,14 @@ public class TestRouteModelResource extends BaseJerseyTest {
|
|||||||
.get(JsonObject.class);
|
.get(JsonObject.class);
|
||||||
Assert.assertEquals(routeModelId, json.getString("id"));
|
Assert.assertEquals(routeModelId, json.getString("id"));
|
||||||
Assert.assertEquals("Workflow validation 1", json.getString("name"));
|
Assert.assertEquals("Workflow validation 1", json.getString("name"));
|
||||||
Assert.assertEquals("[{\"type\":\"VALIDATE\",\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]", json.getString("steps"));
|
Assert.assertEquals("[{\"type\":\"VALIDATE\",\"transitions\":[{\"name\":\"VALIDATED\",\"actions\":[]}],\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]", json.getString("steps"));
|
||||||
|
|
||||||
// Update the route model
|
// Update the route model with actions
|
||||||
target().path("/routemodel/" + routeModelId).request()
|
target().path("/routemodel/" + routeModelId).request()
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
.post(Entity.form(new Form()
|
.post(Entity.form(new Form()
|
||||||
.param("name", "Workflow validation 2")
|
.param("name", "Workflow validation 2")
|
||||||
.param("steps", "[{\"type\":\"APPROVE\",\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]")), JsonObject.class);
|
.param("steps", "[{\"type\":\"APPROVE\",\"transitions\":[{\"name\":\"APPROVED\",\"actions\":[{\"type\":\"ADD_TAG\",\"tag\":\"" + tagRouteId + "\"}]},{\"name\":\"REJECTED\",\"actions\":[]}],\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]")), JsonObject.class);
|
||||||
|
|
||||||
// Get the route model
|
// Get the route model
|
||||||
json = target().path("/routemodel/" + routeModelId)
|
json = target().path("/routemodel/" + routeModelId)
|
||||||
@ -77,7 +85,7 @@ public class TestRouteModelResource extends BaseJerseyTest {
|
|||||||
.get(JsonObject.class);
|
.get(JsonObject.class);
|
||||||
Assert.assertEquals(routeModelId, json.getString("id"));
|
Assert.assertEquals(routeModelId, json.getString("id"));
|
||||||
Assert.assertEquals("Workflow validation 2", json.getString("name"));
|
Assert.assertEquals("Workflow validation 2", json.getString("name"));
|
||||||
Assert.assertEquals("[{\"type\":\"APPROVE\",\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]", json.getString("steps"));
|
Assert.assertEquals("[{\"type\":\"APPROVE\",\"transitions\":[{\"name\":\"APPROVED\",\"actions\":[{\"type\":\"ADD_TAG\",\"tag\":\"" + tagRouteId + "\"}]},{\"name\":\"REJECTED\",\"actions\":[]}],\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]", json.getString("steps"));
|
||||||
|
|
||||||
// Delete the route model
|
// Delete the route model
|
||||||
target().path("/routemodel/" + routeModelId)
|
target().path("/routemodel/" + routeModelId)
|
||||||
|
@ -9,7 +9,6 @@ import javax.json.JsonObject;
|
|||||||
import javax.ws.rs.client.Entity;
|
import javax.ws.rs.client.Entity;
|
||||||
import javax.ws.rs.core.Form;
|
import javax.ws.rs.core.Form;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,14 +49,11 @@ public class TestRouteResource extends BaseJerseyTest {
|
|||||||
Assert.assertEquals(1, routeModels.size());
|
Assert.assertEquals(1, routeModels.size());
|
||||||
|
|
||||||
// Create a document
|
// Create a document
|
||||||
long create1Date = new Date().getTime();
|
|
||||||
json = target().path("/document").request()
|
json = target().path("/document").request()
|
||||||
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, route1Token)
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, route1Token)
|
||||||
.put(Entity.form(new Form()
|
.put(Entity.form(new Form()
|
||||||
.param("title", "My super title document 1")
|
.param("title", "My super title document 1")
|
||||||
.param("description", "My super description for document 1")
|
.param("language", "eng")), JsonObject.class);
|
||||||
.param("language", "eng")
|
|
||||||
.param("create_date", Long.toString(create1Date))), JsonObject.class);
|
|
||||||
String document1Id = json.getString("id");
|
String document1Id = json.getString("id");
|
||||||
|
|
||||||
// Start the default route on document 1
|
// Start the default route on document 1
|
||||||
@ -354,4 +350,100 @@ public class TestRouteResource extends BaseJerseyTest {
|
|||||||
documents = json.getJsonArray("documents");
|
documents = json.getJsonArray("documents");
|
||||||
Assert.assertEquals(0, documents.size());
|
Assert.assertEquals(0, documents.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test actions on workflow step.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAction() {
|
||||||
|
// Login admin
|
||||||
|
String adminToken = clientUtil.login("admin", "admin", false);
|
||||||
|
|
||||||
|
// Create a tag
|
||||||
|
JsonObject json = target().path("/tag").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("name", "Approved")
|
||||||
|
.param("color", "#ff0000")), JsonObject.class);
|
||||||
|
String tagApprovedId = json.getString("id");
|
||||||
|
|
||||||
|
// Create a new route model with actions
|
||||||
|
json = target().path("/routemodel").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("name", "Workflow action 1")
|
||||||
|
.param("steps", "[{\"type\":\"APPROVE\",\"transitions\":[{\"name\":\"APPROVED\",\"actions\":[{\"type\":\"ADD_TAG\",\"tag\":\"" + tagApprovedId + "\"}]},{\"name\":\"REJECTED\",\"actions\":[]}],\"target\":{\"name\":\"administrators\",\"type\":\"GROUP\"},\"name\":\"Check the document's metadata\"}]")), JsonObject.class);
|
||||||
|
String routeModelId = json.getString("id");
|
||||||
|
|
||||||
|
// Create a document
|
||||||
|
json = target().path("/document").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("title", "My super title document 1")
|
||||||
|
.param("description", "My super description for document 1")
|
||||||
|
.param("language", "eng")), JsonObject.class);
|
||||||
|
String document1Id = json.getString("id");
|
||||||
|
|
||||||
|
// Start the route on document 1
|
||||||
|
json = target().path("/route/start").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.post(Entity.form(new Form()
|
||||||
|
.param("documentId", document1Id)
|
||||||
|
.param("routeModelId", routeModelId)), JsonObject.class);
|
||||||
|
JsonObject step = json.getJsonObject("route_step");
|
||||||
|
Assert.assertEquals("Check the document's metadata", step.getString("name"));
|
||||||
|
|
||||||
|
// Check tags on document 1
|
||||||
|
json = target().path("/document/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
JsonArray tags = json.getJsonArray("tags");
|
||||||
|
Assert.assertEquals(0, tags.size());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Check tags on document 1
|
||||||
|
json = target().path("/document/" + document1Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
tags = json.getJsonArray("tags");
|
||||||
|
Assert.assertEquals(1, tags.size());
|
||||||
|
Assert.assertEquals(tagApprovedId, tags.getJsonObject(0).getString("id"));
|
||||||
|
|
||||||
|
// Create a document
|
||||||
|
json = target().path("/document").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.put(Entity.form(new Form()
|
||||||
|
.param("title", "My super title document 2")
|
||||||
|
.param("language", "eng")), JsonObject.class);
|
||||||
|
String document2Id = json.getString("id");
|
||||||
|
|
||||||
|
// Start the route on document 2
|
||||||
|
json = target().path("/route/start").request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.post(Entity.form(new Form()
|
||||||
|
.param("documentId", document2Id)
|
||||||
|
.param("routeModelId", routeModelId)), JsonObject.class);
|
||||||
|
step = json.getJsonObject("route_step");
|
||||||
|
Assert.assertEquals("Check the document's metadata", step.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", document2Id)
|
||||||
|
.param("transition", "REJECTED")), JsonObject.class);
|
||||||
|
|
||||||
|
// Check tags on document 2
|
||||||
|
json = target().path("/document/" + document2Id).request()
|
||||||
|
.cookie(TokenBasedSecurityFilter.COOKIE_NAME, adminToken)
|
||||||
|
.get(JsonObject.class);
|
||||||
|
tags = json.getJsonArray("tags");
|
||||||
|
Assert.assertEquals(0, tags.size());
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user