提交 cded0031 编写于 作者: F Frederik Heremans

Added support for task identity-links

上级 35e5b969
/* Licensed under the Apache License, Version 2.0 (the "License");
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
......@@ -23,6 +24,7 @@ import org.activiti.engine.impl.bpmn.deployer.BpmnDeployer;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.rest.api.engine.variable.BooleanRestVariableConverter;
import org.activiti.rest.api.engine.variable.DateRestVariableConverter;
......@@ -34,6 +36,7 @@ import org.activiti.rest.api.engine.variable.RestVariable.RestVariableScope;
import org.activiti.rest.api.engine.variable.RestVariableConverter;
import org.activiti.rest.api.engine.variable.ShortRestVariableConverter;
import org.activiti.rest.api.engine.variable.StringRestVariableConverter;
import org.activiti.rest.api.identity.RestIdentityLink;
import org.activiti.rest.api.repository.DeploymentResourceResponse;
import org.activiti.rest.api.repository.DeploymentResourceResponse.DeploymentResourceType;
import org.activiti.rest.api.repository.DeploymentResponse;
......@@ -219,6 +222,27 @@ public class RestResponseFactory {
return value;
}
public RestIdentityLink createRestIdentityLink(SecuredResource securedResource, IdentityLink link) {
return createRestIdentityLink(securedResource, link.getType(), link.getUserId(), link.getGroupId(), link.getTaskId());
}
public RestIdentityLink createRestIdentityLink(SecuredResource securedResource, String type, String userId, String groupId, String taskId) {
RestIdentityLink result = new RestIdentityLink();
result.setUser(userId);
result.setGroup(groupId);
result.setType(type);
String family = null;
if(userId != null) {
family = RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS;
} else {
family = RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS;
}
result.setUrl(securedResource.createFullResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, taskId, family, (userId != null ? userId : groupId), type));
return result;
}
/**
* Called once when the converters need to be initialized. Override of custom conversion
* needs to be done between java and rest.
......
......@@ -38,6 +38,9 @@ public final class RestUrls {
public static final String SEGMENT_EXECUTION_RESOURCE = "executions";
public static final String SEGMENT_PROCESS_INSTANCE_RESOURCE = "process-instances";
public static final String SEGMENT_VARIABLES = "variables";
public static final String SEGMENT_IDENTITYLINKS = "identitylinks";
public static final String SEGMENT_IDENTITYLINKS_FAMILY_GROUPS = "groups";
public static final String SEGMENT_IDENTITYLINKS_FAMILY_USERS = "users";
public static final String SEGMENT_VARIABLE_DATA = "data";
/**
......@@ -109,6 +112,16 @@ public final class RestUrls {
*/
public static final String[] URL_TASK_VARIABLE_DATA = {SEGMENT_RUNTIME_RESOURCES, SEGMENT_TASK_RESOURCE, "{0}", SEGMENT_VARIABLES, "{1}", SEGMENT_VARIABLE_DATA};
/**
* URL template for a task's variables: <i>runtime/tasks/{0:taskId}/identitylinks</i>
*/
public static final String[] URL_TASK_IDENTITYLINKS_COLLECTION = {SEGMENT_RUNTIME_RESOURCES, SEGMENT_TASK_RESOURCE, "{0}", SEGMENT_IDENTITYLINKS};
/**
* URL template for a task's variables: <i>runtime/tasks/{0:taskId}/identitylinks/{1:family}/{2:identityId}/{3:type}</i>
*/
public static final String[] URL_TASK_IDENTITYLINK = {SEGMENT_RUNTIME_RESOURCES, SEGMENT_TASK_RESOURCE, "{0}", SEGMENT_IDENTITYLINKS, "{1}", "{2}", "{3}"};
/**
* URL template for execution collection: <i>runtime/executions/{0:executionId}</i>
*/
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.rest.api.identity;
/**
* @author Frederik Heremans
*/
public class RestIdentityLink {
private String url;
private String user;
private String group;
private String type;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
......@@ -24,7 +24,6 @@ import org.activiti.engine.impl.persistence.entity.VariableInstanceEntity;
import org.activiti.engine.task.Task;
import org.activiti.rest.api.ActivitiUtil;
import org.activiti.rest.api.RestResponseFactory;
import org.activiti.rest.api.SecuredResource;
import org.activiti.rest.api.engine.variable.RestVariable;
import org.activiti.rest.api.engine.variable.RestVariable.RestVariableScope;
import org.activiti.rest.application.ActivitiRestServicesApplication;
......@@ -41,8 +40,7 @@ import org.restlet.resource.ResourceException;
/**
* @author Frederik Heremans
*/
public class BaseTaskVariableResource extends SecuredResource {
public class BaseTaskVariableResource extends TaskBasedResource {
public RestVariable getVariableFromRequest(boolean includeBinary) {
String taskId = getAttribute("taskId");
......@@ -112,23 +110,6 @@ public class BaseTaskVariableResource extends SecuredResource {
return variableFound;
}
/**
* Get valid task from request. Throws exception if task doen't exist or if task id is not provided.
*/
protected Task getTaskFromRequest() {
String taskId = getAttribute("taskId");
if (taskId == null) {
throw new ActivitiIllegalArgumentException("The taskId cannot be null");
}
Task task = ActivitiUtil.getTaskService().createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new ActivitiObjectNotFoundException("Could not find a task with id '" + taskId + "'.", Task.class);
}
return task;
}
protected RestVariable setBinaryVariable(Representation representation, Task task, boolean isNew) {
try {
RestletFileUpload upload = new RestletFileUpload(new DiskFileItemFactory());
......
......@@ -17,6 +17,7 @@ import java.util.HashMap;
import java.util.List;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.impl.TaskQueryProperty;
import org.activiti.engine.query.QueryProperty;
import org.activiti.engine.task.DelegationState;
......@@ -317,4 +318,21 @@ public class TaskBasedResource extends SecuredResource {
}
}
}
/**
* Get valid task from request. Throws exception if task doen't exist or if task id is not provided.
*/
protected Task getTaskFromRequest() {
String taskId = getAttribute("taskId");
if (taskId == null) {
throw new ActivitiIllegalArgumentException("The taskId cannot be null");
}
Task task = ActivitiUtil.getTaskService().createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new ActivitiObjectNotFoundException("Could not find a task with id '" + taskId + "'.", Task.class);
}
return task;
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.rest.api.task;
import java.util.ArrayList;
import java.util.List;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.rest.api.ActivitiUtil;
import org.activiti.rest.api.RestResponseFactory;
import org.activiti.rest.api.identity.RestIdentityLink;
import org.activiti.rest.application.ActivitiRestServicesApplication;
import org.restlet.data.Status;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
/**
* @author Frederik Heremans
*/
public class TaskIdentityLinkCollectionResource extends TaskBasedResource {
@Get
public List<RestIdentityLink> getIdentityLinks() {
if(!authenticate())
return null;
List<RestIdentityLink> result = new ArrayList<RestIdentityLink>();
Task task = getTaskFromRequest();
List<IdentityLink> identityLinks = ActivitiUtil.getTaskService().getIdentityLinksForTask(task.getId());
RestResponseFactory responseFactory = getApplication(ActivitiRestServicesApplication.class).getRestResponseFactory();
for(IdentityLink link : identityLinks) {
result.add(responseFactory.createRestIdentityLink(this, link));
}
return result;
}
@Post
public RestIdentityLink createIdentityLink(RestIdentityLink identityLink) {
if(!authenticate())
return null;
Task task = getTaskFromRequest();
if(identityLink.getGroup() == null && identityLink.getUser() == null) {
throw new ActivitiIllegalArgumentException("A group or a user is required to create an identity link.");
}
if(identityLink.getGroup() != null && identityLink.getUser() != null) {
throw new ActivitiIllegalArgumentException("Only one of user or group can be used to create an identity link.");
}
if(identityLink.getType() == null) {
throw new ActivitiIllegalArgumentException("The identity link type is required.");
}
if(identityLink.getGroup() != null) {
ActivitiUtil.getTaskService().addGroupIdentityLink(task.getId(), identityLink.getGroup(), identityLink.getType());
} else {
ActivitiUtil.getTaskService().addUserIdentityLink(task.getId(), identityLink.getUser(), identityLink.getType());
}
setStatus(Status.SUCCESS_CREATED);
return getApplication(ActivitiRestServicesApplication.class).getRestResponseFactory()
.createRestIdentityLink(this, identityLink.getType(), identityLink.getUser(), identityLink.getGroup(), task.getId());
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.rest.api.task;
import java.util.ArrayList;
import java.util.List;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.rest.api.ActivitiUtil;
import org.activiti.rest.api.RestResponseFactory;
import org.activiti.rest.api.RestUrls;
import org.activiti.rest.api.identity.RestIdentityLink;
import org.activiti.rest.application.ActivitiRestServicesApplication;
import org.restlet.data.Status;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
/**
* @author Frederik Heremans
*/
public class TaskIdentityLinkFamilyResource extends TaskBasedResource {
@Get
public List<RestIdentityLink> getIdentityLinksForFamily() {
Task task = getTaskFromRequest();
// Extract and validate identity link from URL
String family = getAttribute("family");
if(family == null || (!RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS.equals(family)
&& !RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family))) {
throw new ActivitiIllegalArgumentException("Identity link family should be 'users' or 'groups'.");
}
boolean isUser = family.equals(RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS);
List<RestIdentityLink> results = new ArrayList<RestIdentityLink>();
RestResponseFactory responseFactory = getApplication(ActivitiRestServicesApplication.class).getRestResponseFactory();
List<IdentityLink> allLinks = ActivitiUtil.getTaskService().getIdentityLinksForTask(task.getId());
for(IdentityLink link : allLinks) {
boolean match = false;
if(isUser) {
match = link.getUserId() != null;
} else {
match = link.getGroupId() != null;
}
if(match) {
results.add(responseFactory.createRestIdentityLink(this, link));
}
}
return results;
}
@Delete
public void deleteIdentityLink() {
Task task = getTaskFromRequest();
// Extract and validate identity link from URL
String family = getAttribute("family");
String identityId = getAttribute("identityId");
String type = getAttribute("type");
validateIdentityLinkArguments(family, identityId, type);
// Check if identitylink to delete exists
getIdentityLink(family, identityId, type, task.getId());
if(RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family)) {
ActivitiUtil.getTaskService().deleteUserIdentityLink(task.getId(), identityId, type);
} else {
ActivitiUtil.getTaskService().deleteGroupIdentityLink(task.getId(), identityId, type);
}
setStatus(Status.SUCCESS_NO_CONTENT);
}
protected void validateIdentityLinkArguments(String family, String identityId, String type) {
if(identityId == null) {
throw new ActivitiIllegalArgumentException("IdentityId is required.");
}
if(type == null) {
throw new ActivitiIllegalArgumentException("Type is required.");
}
}
protected IdentityLink getIdentityLink(String family, String identityId, String type, String taskId) {
boolean isUser = family.equals(RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS);
// Perhaps it would be better to offer getting a single identitylink from the API
List<IdentityLink> allLinks = ActivitiUtil.getTaskService().getIdentityLinksForTask(taskId);
for(IdentityLink link : allLinks) {
boolean rightIdentity = false;
if(isUser) {
rightIdentity = identityId.equals(link.getUserId());
} else {
rightIdentity = identityId.equals(link.getGroupId());
}
if(rightIdentity && link.getType().equals(type)) {
return link;
}
}
throw new ActivitiObjectNotFoundException("Could not find the requested identity link.", IdentityLink.class);
}
}
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.rest.api.task;
import java.util.List;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.rest.api.ActivitiUtil;
import org.activiti.rest.api.RestUrls;
import org.activiti.rest.api.identity.RestIdentityLink;
import org.activiti.rest.application.ActivitiRestServicesApplication;
import org.restlet.data.Status;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
/**
* @author Frederik Heremans
*/
public class TaskIdentityLinkResource extends TaskBasedResource {
@Get
public RestIdentityLink getIdentityLink() {
Task task = getTaskFromRequest();
// Extract and validate identity link from URL
String family = getAttribute("family");
String identityId = getAttribute("identityId");
String type = getAttribute("type");
validateIdentityLinkArguments(family, identityId, type);
IdentityLink link = getIdentityLink(family, identityId, type, task.getId());
return getApplication(ActivitiRestServicesApplication.class).getRestResponseFactory()
.createRestIdentityLink(this, link);
}
@Delete
public void deleteIdentityLink() {
Task task = getTaskFromRequest();
// Extract and validate identity link from URL
String family = getAttribute("family");
String identityId = getAttribute("identityId");
String type = getAttribute("type");
validateIdentityLinkArguments(family, identityId, type);
// Check if identitylink to delete exists
getIdentityLink(family, identityId, type, task.getId());
if(RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family)) {
ActivitiUtil.getTaskService().deleteUserIdentityLink(task.getId(), identityId, type);
} else {
ActivitiUtil.getTaskService().deleteGroupIdentityLink(task.getId(), identityId, type);
}
setStatus(Status.SUCCESS_NO_CONTENT);
}
protected void validateIdentityLinkArguments(String family, String identityId, String type) {
if(family == null || (!RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS.equals(family)
&& !RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS.equals(family))) {
throw new ActivitiIllegalArgumentException("Identity link family should be 'users' or 'groups'.");
}
if(identityId == null) {
throw new ActivitiIllegalArgumentException("IdentityId is required.");
}
if(type == null) {
throw new ActivitiIllegalArgumentException("Type is required.");
}
}
protected IdentityLink getIdentityLink(String family, String identityId, String type, String taskId) {
boolean isUser = family.equals(RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS);
// Perhaps it would be better to offer getting a single identitylink from the API
List<IdentityLink> allLinks = ActivitiUtil.getTaskService().getIdentityLinksForTask(taskId);
for(IdentityLink link : allLinks) {
boolean rightIdentity = false;
if(isUser) {
rightIdentity = identityId.equals(link.getUserId());
} else {
rightIdentity = identityId.equals(link.getGroupId());
}
if(rightIdentity && link.getType().equals(type)) {
return link;
}
}
throw new ActivitiObjectNotFoundException("Could not find the requested identity link.", IdentityLink.class);
}
}
......@@ -110,25 +110,7 @@ public class TaskResource extends TaskBasedResource {
}
getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
}
/**
* Get valid task from request. Throws exception if task doen't exist or if task id is not provided.
*/
protected Task getTaskFromRequest() {
String taskId = getAttribute("taskId");
if (taskId == null) {
throw new ActivitiIllegalArgumentException("The taskId cannot be null");
}
Task task = ActivitiUtil.getTaskService().createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new ActivitiObjectNotFoundException("Could not find a task with id '" + taskId + "'.", Task.class);
}
return task;
}
protected void completeTask(Task task, TaskActionRequest actionRequest) {
// TODO: take into account variables
if(actionRequest.getAssignee() != null) {
......
......@@ -56,6 +56,9 @@ import org.activiti.rest.api.repository.ProcessDefinitionCollectionResource;
import org.activiti.rest.api.repository.ProcessDefinitionResource;
import org.activiti.rest.api.repository.SimpleWorkflowResource;
import org.activiti.rest.api.task.TaskCollectionResource;
import org.activiti.rest.api.task.TaskIdentityLinkCollectionResource;
import org.activiti.rest.api.task.TaskIdentityLinkFamilyResource;
import org.activiti.rest.api.task.TaskIdentityLinkResource;
import org.activiti.rest.api.task.TaskQueryResource;
import org.activiti.rest.api.task.TaskResource;
import org.activiti.rest.api.task.TaskVariableCollectionResource;
......@@ -83,7 +86,9 @@ public class RestServicesInit {
router.attach("/runtime/tasks/{taskId}/variables", TaskVariableCollectionResource.class);
router.attach("/runtime/tasks/{taskId}/variables/{variableName}", TaskVariableResource.class);
router.attach("/runtime/tasks/{taskId}/variables/{variableName}/data", TaskVariableDataResource.class);
// router.attach("/runtime/tasks/{taskId}/identitylinks", TaskIdentityLinkCollectionResource.class);
router.attach("/runtime/tasks/{taskId}/identitylinks", TaskIdentityLinkCollectionResource.class);
router.attach("/runtime/tasks/{taskId}/identitylinks/{family}", TaskIdentityLinkFamilyResource.class);
router.attach("/runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}", TaskIdentityLinkResource.class);
router.attach("/query/tasks", TaskQueryResource.class);
......
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.rest.api.runtime;
import java.util.List;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.test.Deployment;
import org.activiti.rest.BaseRestTestCase;
import org.activiti.rest.api.RestUrls;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException;
/**
* Test for all REST-operations related to a identity links on a Task resource.
*
* @author Frederik Heremans
*/
public class TaskIdentityLinkResourceTest extends BaseRestTestCase {
/**
* Test getting all identity links.
* GET runtime/tasks/{taskId}/identitylinks
*/
@Deployment
public void testGetIdentityLinks() throws Exception {
// Test candidate user/groups links + manual added identityLink
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("identityLinkProcess");
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
taskService.addUserIdentityLink(task.getId(), "john", "customType");
assertEquals(3, taskService.getIdentityLinksForTask(task.getId()).size());
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINKS_COLLECTION, task.getId()));
// Execute the request
Representation response = client.get();
assertEquals(Status.SUCCESS_OK, client.getResponse().getStatus());
JsonNode responseNode = objectMapper.readTree(response.getStream());
assertNotNull(responseNode);
assertTrue(responseNode.isArray());
assertEquals(3, responseNode.size());
boolean groupCandidateFound = false;
boolean userCandidateFound = false;
boolean customLinkFound = false;
for(int i=0; i < responseNode.size(); i++) {
ObjectNode link = (ObjectNode) responseNode.get(i);
assertNotNull(link);
if(!link.get("user").isNull()) {
if(link.get("user").getTextValue().equals("john")) {
assertEquals("customType", link.get("type").getTextValue());
assertTrue(link.get("group").isNull());
assertTrue(link.get("url").getTextValue().endsWith(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, task.getId(), "users", "john", "customType")));
customLinkFound = true;
} else {
assertEquals("kermit", link.get("user").getTextValue());
assertEquals("candidate", link.get("type").getTextValue());
assertTrue(link.get("group").isNull());
assertTrue(link.get("url").getTextValue().endsWith(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, task.getId(), "users", "kermit", "candidate")));
userCandidateFound = true;
}
} else if(!link.get("group").isNull()) {
assertEquals("sales", link.get("group").getTextValue());
assertEquals("candidate", link.get("type").getTextValue());
assertTrue(link.get("user").isNull());
assertTrue(link.get("url").getTextValue().endsWith(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, task.getId(), RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS, "sales", "candidate")));
groupCandidateFound = true;
}
}
assertTrue(groupCandidateFound);
assertTrue(userCandidateFound);
assertTrue(customLinkFound);
}
/**
* Test getting all identity links.
* POST runtime/tasks/{taskId}/identitylinks
*/
public void testCreateIdentityLink() throws Exception {
try {
Task task = taskService.newTask();
taskService.saveTask(task);
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINKS_COLLECTION, task.getId()));
// Add user link
ObjectNode requestNode = objectMapper.createObjectNode();
requestNode.put("user", "kermit");
requestNode.put("type", "myType");
Representation response = client.post(requestNode);
assertEquals(Status.SUCCESS_CREATED, client.getResponse().getStatus());
JsonNode responseNode = objectMapper.readTree(response.getStream());
assertNotNull(responseNode);
assertEquals("kermit", responseNode.get("user").getTextValue());
assertEquals("myType", responseNode.get("type").getTextValue());
assertTrue(responseNode.get("group").isNull());
assertTrue(responseNode.get("url").getTextValue().endsWith(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, task.getId(), RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS, "kermit", "myType")));
// Add group link
requestNode = objectMapper.createObjectNode();
requestNode.put("group", "sales");
requestNode.put("type", "myType");
client.release();
response = client.post(requestNode);
assertEquals(Status.SUCCESS_CREATED, client.getResponse().getStatus());
responseNode = objectMapper.readTree(response.getStream());
assertNotNull(responseNode);
assertEquals("sales", responseNode.get("group").getTextValue());
assertEquals("myType", responseNode.get("type").getTextValue());
assertTrue(responseNode.get("user").isNull());
assertTrue(responseNode.get("url").getTextValue().endsWith(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, task.getId(), RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_GROUPS, "sales", "myType")));
// Test with unexisting task
client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINKS_COLLECTION, "unexistingtask"));
try {
client.post(null);
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_NOT_FOUND, expected.getStatus());
assertEquals("Could not find a task with id 'unexistingtask'.", expected.getStatus().getDescription());
}
// Test with no user/group task
client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINKS_COLLECTION, task.getId()));
requestNode = objectMapper.createObjectNode();
requestNode.put("type", "myType");
try {
client.post(requestNode);
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_BAD_REQUEST, expected.getStatus());
assertEquals("A group or a user is required to create an identity link.", expected.getStatus().getDescription());
}
// Test with no user/group task
requestNode = objectMapper.createObjectNode();
requestNode.put("type", "myType");
requestNode.put("user", "kermit");
requestNode.put("group", "sales");
try {
client.release();
client.post(requestNode);
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_BAD_REQUEST, expected.getStatus());
assertEquals("Only one of user or group can be used to create an identity link.", expected.getStatus().getDescription());
}
// Test with no type
requestNode = objectMapper.createObjectNode();
requestNode.put("group", "sales");
try {
client.release();
client.post(requestNode);
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_BAD_REQUEST, expected.getStatus());
assertEquals("The identity link type is required.", expected.getStatus().getDescription());
}
} finally {
// Clean adhoc-tasks even if test fails
List<Task> tasks = taskService.createTaskQuery().list();
for(Task task : tasks) {
taskService.deleteTask(task.getId(), true);
}
}
}
/**
* Test getting a single identity link for a task.
* GET runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}
*/
public void testGetSingleIdentityLink() throws Exception {
try {
Task task = taskService.newTask();
taskService.saveTask(task);
taskService.addUserIdentityLink(task.getId(), "kermit", "myType");
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(
RestUrls.URL_TASK_IDENTITYLINK, task.getId(), "users", "kermit", "myType"));
Representation response = client.get();
assertEquals(Status.SUCCESS_OK, client.getResponse().getStatus());
JsonNode responseNode = objectMapper.readTree(response.getStream());
assertNotNull(responseNode);
assertEquals("kermit", responseNode.get("user").getTextValue());
assertEquals("myType", responseNode.get("type").getTextValue());
assertTrue(responseNode.get("group").isNull());
assertTrue(responseNode.get("url").getTextValue().endsWith(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, task.getId(), RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS, "kermit", "myType")));
// Test with unexisting task
client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, "unexistingtask", RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS, "kermit", "myType"));
try {
client.get();
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_NOT_FOUND, expected.getStatus());
assertEquals("Could not find a task with id 'unexistingtask'.", expected.getStatus().getDescription());
}
} finally {
// Clean adhoc-tasks even if test fails
List<Task> tasks = taskService.createTaskQuery().list();
for(Task task : tasks) {
taskService.deleteTask(task.getId(), true);
}
}
}
/**
* Test deleting a single identity link for a task.
* DELETE runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}
*/
public void testDeleteSingleIdentityLink() throws Exception {
try {
Task task = taskService.newTask();
taskService.saveTask(task);
taskService.addUserIdentityLink(task.getId(), "kermit", "myType");
ClientResource client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(
RestUrls.URL_TASK_IDENTITYLINK, task.getId(), "users", "kermit", "myType"));
client.delete();
assertEquals(Status.SUCCESS_NO_CONTENT, client.getResponse().getStatus());
// Test with unexisting identitylink
client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, task.getId(), RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS, "kermit", "unexistingtype"));
try {
client.delete();
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_NOT_FOUND, expected.getStatus());
assertEquals("Could not find the requested identity link.", expected.getStatus().getDescription());
}
// Test with unexisting task
client = getAuthenticatedClient(RestUrls.createRelativeResourceUrl(RestUrls.URL_TASK_IDENTITYLINK, "unexistingtask", RestUrls.SEGMENT_IDENTITYLINKS_FAMILY_USERS, "kermit", "myType"));
try {
client.delete();
fail("Exception expected");
} catch(ResourceException expected) {
assertEquals(Status.CLIENT_ERROR_NOT_FOUND, expected.getStatus());
assertEquals("Could not find a task with id 'unexistingtask'.", expected.getStatus().getDescription());
}
} finally {
// Clean adhoc-tasks even if test fails
List<Task> tasks = taskService.createTaskQuery().list();
for(Task task : tasks) {
taskService.deleteTask(task.getId(), true);
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:activiti="http://activiti.org/bpmn"
targetNamespace="OneTaskCategory">
<process id="identityLinkProcess" name="The One Task Process">
<documentation>One task process description</documentation>
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="processTask" />
<userTask id="processTask" name="Process task" activiti:candidateUsers="kermit" activiti:candidateGroups="sales">
<documentation>Process task description</documentation>
</userTask>
<sequenceFlow id="flow2" sourceRef="processTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
\ No newline at end of file
......@@ -2626,6 +2626,241 @@ The request body should be an array containing one or more JSON-objects represen
</table>
</para>
</section>
<section>
<title>Get all identity links for a single task</title>
<para>
<programlisting>GET runtime/tasks/{taskId}/identitylinks</programlisting>
</para>
<para>
<table>
<title>URL parameters</title>
<tgroup cols='3'>
<thead>
<row>
<entry>Parameter</entry>
<entry>Required</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>taskId</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The id of the task to get the identity links for.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<table>
<title>Response codes</title>
<tgroup cols='2'>
<thead>
<row>
<entry>Response code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>200</entry>
<entry>Indicates the task was found and the requested idenity links are returned.</entry>
</row>
<row>
<entry>404</entry>
<entry>Indicates the requested task was not found.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<emphasis role="bold">Success response body:</emphasis>
<programlisting>
[
{
"userId" : "kermit",
"groupId" : null,
"type" : "candidate",
"url" : "http://localhost:8081/activiti-rest/service/runtime/tasks/100/identitylinks/users/kermit/candidate"
},
{
"userId" : null,
"groupId" : "sales",
"type" : "candidate",
"url" : "http://localhost:8081/activiti-rest/service/runtime/tasks/100/identitylinks/groups/sales/candidate"
},
...
]</programlisting>
</para>
</section>
<section>
<title>Get all identitylinks for a task for either groups or users</title>
<para>
<programlisting>GET runtime/tasks/{taskId}/identitylinks/users
GET runtime/tasks/{taskId}/identitylinks/groups</programlisting>
</para>
<para>
Returns only identity links targetting either users or groups. Response body and status-codes are exactly the same as when getting the full list of identity links for a task.
</para>
</section>
<section>
<title>Get a single identity link on a task</title>
<para>
<programlisting>GET runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}</programlisting>
</para>
<para>
<table>
<title>URL parameters</title>
<tgroup cols='3'>
<thead>
<row>
<entry>Parameter</entry>
<entry>Required</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>taskId</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The id of the task .</entry>
</row>
<row>
<entry>family</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>Either <literal>groups</literal> or <literal>users</literal>, depending on what kind of identity is targetted.</entry>
</row>
<row>
<entry>identityId</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The id of the identity.</entry>
</row>
<row>
<entry>type</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The type of identity link.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<table>
<title>Response codes</title>
<tgroup cols='2'>
<thead>
<row>
<entry>Response code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>200</entry>
<entry>Indicates the task and identity link was found and returned.</entry>
</row>
<row>
<entry>404</entry>
<entry>Indicates the requested task was not found or the task doesn't have the requested identityLink. The status contains additional information about this error.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<emphasis role="bold">Success response body:</emphasis>
<programlisting>
{
"userId" : null,
"groupId" : "sales",
"type" : "candidate",
"url" : "http://localhost:8081/activiti-rest/service/runtime/tasks/100/identitylinks/groups/sales/candidate"
}</programlisting>
</para>
</section>
<section>
<title>Delete a single identity link on a task</title>
<para>
<programlisting>DELETE runtime/tasks/{taskId}/identitylinks/{family}/{identityId}/{type}</programlisting>
</para>
<para>
<table>
<title>URL parameters</title>
<tgroup cols='3'>
<thead>
<row>
<entry>Parameter</entry>
<entry>Required</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>taskId</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The id of the task.</entry>
</row>
<row>
<entry>family</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>Either <literal>groups</literal> or <literal>users</literal>, depending on what kind of identity is targetted.</entry>
</row>
<row>
<entry>identityId</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The id of the identity.</entry>
</row>
<row>
<entry>type</entry>
<entry>Yes</entry>
<entry>String</entry>
<entry>The type of identity link.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
<table>
<title>Response codes</title>
<tgroup cols='2'>
<thead>
<row>
<entry>Response code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>204</entry>
<entry>Indicates the task and identity link were found and the link has been deleted. Response-body is intentionally empty.</entry>
</row>
<row>
<entry>404</entry>
<entry>Indicates the requested task was not found or the task doesn't have the requested identityLink. The status contains additional information about this error.</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</section>
</section>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册